标题：KMP
朴素算法
先看看最“朴素”的算法：
//find a template in a string.
#include<string.h>
#include<stdio.h>
int Index(char *S,char *T,int pos)//pos记录从哪一位开始匹配可以直接用0代替
{
int k=pos,j=0; 
while(k <strlen(S) && j<strlen(T))//未超出字符串的长度
{
if (S[k] == T[j]) { ++k; ++j;} //如果相同，则继续向后比较
else {k = k-j+1; j =0;} //如果不同，就回溯，重新查找
}
if (j == strlen(T)) return k-strlen（T）； 
else return 0;
}
KMP算法
一种由Knuth(D.E.Knuth)、Morris(J.H.Morris）和Pratt(V.R.Pratt）三人设计的线性时间字符串匹配算法。这个算法不用计算变迁函数δ，匹配时间为Θ（n），只用到辅助函数π[1，m]，它是在Θ（m）时间内，根据模式预先计算出来的。数组π使得我们可以按需要，“现场”有效的计算（在平摊意义上来说）变迁函数δ。粗略地说，对任意状态q=0，1，…，m和任意字符a∈Σ，π[q]的值包含了与a无关但在计算δ（q，a）时需要的信息。由于数组π只有m个元素，而δ有Θ（m∣Σ∣）个值，所以通过预先计算π而不是δ，使得时间减少了一个Σ因子。[1]​
KMP算法是通过分析子串，预先计算每个位置发生不匹配的时候，所需GOTO的下一个比较位置，整理出来一个next数组，然后在上面的算法中使用。
算法讲解
当我们分析一个子串时，例如：abcabcddes. 需要分析一下，每个字符x前面最多有多少个连续的字符和字符串从初始位置开始的字符匹配。然后+1就行了（别忘了，我们的字符串都是从索引1开始的）当然，不要相同位置自己匹配，默认第一个字符的匹配数是0。
定义
设字符串为 x1x2x3...xn，其中x1，x2，x3，... xi，... xn均是字符，设ai为字符xi对应的整数。则a=m，当且仅当满足如下条件：字符串x1x2...xm equals 字符串x(i-m+1）...xi-1 xi 并且x1x2...xm x(m+1） unequals x(i-m) x(i-m+1）...xi-1 xi。
举例
abcabcddes
0111234111 
|----------------------默认是0
--| | |-----------------不能自己在相同位置进行字符匹配，所以这里认为没有匹配字符串，所以0+1 =1，继续从1开始匹配
------| | |-----------前面的字符和开始位置的字符相同，所以是2,3,4
-----------| | | |-------不匹配只能取1。
希望能明白的是，如果开始字符是 Ch1的话，那么我们就是要在串中第2个Ch1后面的位置开始自己和自己匹配，计算最大的吻合度。
程序写出来就是：
void GetNext(char* T,int *next)
{
int k=1,j=0;
next[1]=0;
while(k〈 T[0]){
if (j ==0 || T[k] == T[j]) 
{ 
++k; 
++j; 
next[k] = j;
}
else j= next[j];
}
}
但是这个不是最优的，因为他没有考虑aaaaaaaaaaaaaaaaaaab的情况，这样前面会出现大量的1，这样的算法复杂度已经和最初的朴素算法没有区别了。所以稍微改动一下：
void GetNextEx(char *T,int *next)
{
int k=1,j=0; next[1] = 0;
while(k < T[0])
{
if (j == 0 || T[k] == T[j])
{
++k; ++j;
if (T[k] == T[j])
next[k] = next[j];
else
next[k] = j;
}
else j = next[j];
}
}
现在我们已经可以得到这个next字符串的值了，接下来就是KMP算法的本体了：
相当简单：
int KMP(char* S,char* T,int pos)
{
int k=pos,j=1;
int tt=strlen(S);
while (k<tt){ 
if (S[k] == T[j]){ ++k; ++j; }
else j = next[j];
}
if (j>T[0]) return k-T[0];
else return 0;
}
和朴素算法相比，只是修改一句话而已，但是算法复杂度从O(m*n) 变成了：O(m+n)
伪代码
KMP-MATCHER(T，P)
1　n ← length[T]
2　m ←length[P]
3　π ← COMPUTE-PREFⅨ-FUNCTION(P)
4　q ← 0　△Number of characters matched.
5　for i ← 1 to n　 △Scan the text from left to right.
6　do while q>0 and P[q+1]≠T[i]
7　doq ← π[q]　△Next character does not match.
8　ifP[q+1]=T[i]
9　thenq ← q+1　 △Next character matches.
10　ifq=m　 △Is all of P matched?
11　then print “Pattern occurs with shift” i-m
12　q ← π[q]　 △Look for the next match.
COMPUTE-PERFⅨ-FUNCTION(P)
1　m ← length[P]
2　π[1] ← 0
3　k ← 0
4　forq ← 2 to m
5　do while k>0 and P[k+1]≠P[q]
6　dok ← π[k]
7　ifP[k+1]=P[q]
8　thenk ← k+1
9　π[q] ← k
10　return π[1]​
c++实现
//c++实现的KMP算法，所有涉及字符串，其初始下标从0开始（上述算法均是从1开始）
//example: char s[100],t[100];cin>>s>>t;KMP(s,t);
//获取待查询模式的next数组
int* get_next(char* T,int* next){
int i = 0,j = -1;
int length = strlen(T);
int *temp = next;
*next = -1;
while(i< length){
if(j==-1 || *(T+i)==*(T+j)){
i++;
j++;
//优化后的get_next方法，可以防止出现形如"aaaaab"这种模式的计算退化
if(*(T+i)!=*(T+j))
*(next+i)=j;
else
*(next+i)=*(next+j);
}
else
j=*(next+j);
}
return temp;
}
//KMP算法
int KMP(char *S,char *T){
int S_Length = strlen(S);
int T_Length = strlen(T);
//若模式长度大于字符串，则直接返回查询失败
if(S_Length < T_Length)
return 0;
int i = 0,j = 0;
int* next = new int[T_Length];
get_next(T,next);
while(i < S_Length && j < T_Length){
if(j == -1 || *(S+i) == *(T+j)){
i++;
j++;
}
else
j=*(next+j);
}
if(j>=T_Length)
return i-T_Length;
return 0;
}
在此提供一个更简明的适用于字符串的kmp实现：
#include<iostream>
#include<string.h>
int next[100];
void getnext(char b[])
{
int i=1,j=0; //i是每个位子，j是回退的位子 
next[1]=0; 
while(i<=strlen(b))
{
if(j==0||b[i-1]==b[j-1])
{
i++;
j++;
next[i]=j; 
}
else j=next[j]; //用上一个的 回退关系 
} 
} 
int kmp(char a[],char b[])
{
int i=1,j=1; //i是主串中的位子 ，j匹配串的位子 
while(i<=strlen(a)&&j<=strlen(b))
{ 
if(j==0||a[i-1]==b[j-1])
{
i++;
j++; 
}
else j=next[j];
} 
if(j>strlen(b))
return i-strlen(b);
else return 0;
}
int main()
{ 
char a[40],b[40];
printf("要匹配的主串：\n");
scanf("%s",a);
printf("要匹配的子串：\n");
scanf("%s",b);
getnext(b);
printf("输出next值：\n");
for(int i=1;i<=strlen(b);i++)
printf("%d ",next[i]); 
printf("\n");
printf("%d",kmp(a,b)); 
system("pause"); 
main(); 
return 0; 
}
最大匹配
摘要给定两个串S和T，长分别m和n，本文给出了一个找出二串间最大匹配的算法。该算法可用于比较两个串S和T的相似程度，它与串的模式匹配有别。关键词模式匹配 串的最大匹配 算法
Algorithm on Maximal Matching of Strings
Lin YuCai Xiang YongHong Zhang ChunXia Zhang JianJun
（Computer Science Department of Yunnan Normal University Kunming 650092）
ABSTRACT Given Two Strings S of length m and T of length n，the paper presents an algorithm which finds the maximal matching of them. The algorithm can be used to compare the similarility of the two strings S and T,it is different with the strings' pattren matching. 
KEY WORDS Pattern Matching Maximal Matching of Strings Algorithm
提出问题
字符串的模式匹配主要用于文本处理，例如文本编辑。文本数据的存储（文本压缩）和数据检索系统。所谓字符串的模式匹配[2]，就是给定两个字符串S和T，长度分别为m和n，找出T中出现的一个或多个或所有的S，在这方面已经取得了不少进展[3][4][5][6][7][8][9][10][11]。本文从文本处理的另一个角度出发，找出两个串的最大匹配，比较其相似程度[1]。它主要应用于文本比较，特别是在计算机辅助教学中。显然前者要找S的完全匹配，而后者并无此要求。例如，若S=ABCD，T=EFABCDX，那么模式匹配的结果就是找出了T中的一个ABCD，而我们算法的结果就是S能与T的ABCD完全匹配，但是T中还有3个字符是比S多出来的，也就是说在S中有100%的字符与T中的匹配，而在T中有57%的字符与S中的匹配。若S= ABCDFE，T=AFXBECDY。则在模式匹配中S与T无匹配项，但在我们的算法中就能发现T中存在A，B，C，D，但D后不存在E，F。而且S中也存在A，B，C，D，且具有顺序性。这样就能公正地评价S，T的区别。得知其相似程度。
文章的组织如下：首先介绍基本定义和问题的描述；第三节是算法设计；最后是本文总结。
问题描述
设∑为任意有限集，其元称为字符，w：∑→N为∑到N的函数，称为∑的权函数（注：本文仅讨论权值恒为1的情况）。∑*为∑上的有限字符串集合，那么对任意S，T∈∑*，设S=a1a2…am，T=b1b2…bn，m>0，n>0。记<m>={1,2，…，m},<n>={1,2，…，n}，则称{(i,j）∣i∈<m>；，j∈<n>；，ai=bj}为S与T的匹配关系集，记作M（S，T），称M为S与T的一个（容许）匹配，若对任意（i,j），（i',j'）∈，① i< i'，当且仅当j< j'，② i= i'当且仅当j= j'。S与T的匹配中满足 最大者，称为S与T的最大匹配。若C(i,j）为N上的m×n矩阵，且满足：
则称矩阵C为串S与T的匹配关系阵。
于是求串S与T的最大匹配，等价于求C中的一个最大独立点集M，它满足，若ci,j，ci',j'∈M，则i< i' 当且仅当j< j'，i=i'当且仅当j=j'。我们称这样的最大独立点集为C的最大C-独立点集。
例：设∑为所有字母的集合，对任意x∈∑，w（x）≡1，设S与T分别为：S=“BOOKNEWS”，T=“NEWBOOKS”。则我们可以得到S与T两个匹配：
这里=5；
这里 =4。
显然为串S与T的最大匹配。
S与T的匹配关系阵C可表示如下：
其中带圈的部分为一最大C-独立点集。
算法设计
我们仅就权值为一的情况进行讨论。
设S和T为任意给定串，C为的S与T匹配关系阵，那么由2的讨论知，求S与T的最大匹配问题，等价于求C的最大C-独立点集问题。因而，为了解决我们的问题，只要给出求C的最大C-独立点集的算法就可以了。
显然，为了求出C的最大C-独立点集，我们可以采用这样的方法：搜索C的所有C-独立点集，并找出它的最大者。这种方法是可行的，但并不是非常有效的。这会使问题变得很繁，复杂度很大。因此，我们先对问题进行分析。
在下面的讨论中，我们把C的任一C-独立点集={ai1,j1，…，ais,js}，记作=ai1,j1…ais,js，i1 <；…< is。于是可看作阵C中以1为节点的一条路，满足：对路中的任意两节点，均有某一节点位于另一节点的右下方。称这种路为右下行路。
于是求C-独立点集等价于求阵C的右下行路。这种求右下行路的搜索可以逐行往下进行。
命题1. 若 =αai,jβ和ψ=α'ai,jσ为C的两个C-独立点集，且α为α'的加细，则存在C-独立点集'=αai,jδ，满足≥。
命题2. 若 =αai,jβ和ψ=α'ai+k,jσ为C的两个C-独立点集，且≥，则存在C-独立点集'=αai,jδ，满足≥。
命题3. 若 =αai,jβ和ψ=α'ai,j+kσ为C的两个C-独立点集，且≥，则存在C-独立点集'=αai,jδ，满足≥。
由命题1知，在搜索右下行路的过程中，如果已获得了某一C-独立点集的某一初始截段αai,j和另一C-独立点集ψ的某一初始截段α'ai,j，且有≤，则我们可以停止对ψ的进一步搜索。
由命题2知，在搜索右下行路的过程中，在某一列j存在某两个C-独立点集的某初始截段=ai1,j1…ais,j和ψ=al1,m1…alt,j，如果≥，但lt>is，则我们可以停止对ψ的进一步搜索。
由命题3知，在搜索右下行路的过程中，在某一行i存在某两个C-独立点集的某初始截段=ai1,j1…ai,js和ψ=ai1,m1…ai,mt，如果≥，但mt>js，则我们可以停止对ψ的进一步搜索。
由此可见，并不要求搜索所有C的最大C-独立点集，而可以采用比这简单得多的方法进行计算。那么按照我们上面的三个命题，来看如下实例：
首先我们得到=B（在上的节点用①表示），我们向右下方找路，可以发现，在第4列有两个1，根据命题2，我们选择上面的一个1，也就是说选择第1行的那个1，而不要第2行的那个1。同时我们也发现在第1行也有两个1，由命题3知，我们选择左边的那个1，即第4列的那个1。此时=BO。但是当我们的算法运行到第4行时，=BOOK，由于K在第3行第6列，而本行的1在第1列，在路最后一个节点K的左边，那么我们必须新建一条路ψ，因为我们并不能确定是否以后就有≥，当算法运行到第6行时，=BOOK，ψ=NEW，=4，=3，我们将S链到路上，此时我们得到最长右下行路=BOOKS，=5。这样我们就可以计算出这两个字符串的匹配程度。
在我们的算法设计过程中，用到了两个技巧。技巧之一，矩阵C不用存储，是动态建立的，节省了空间。技巧之二，本算法并不要求所有的S与T中所有的元素都相互进行比较，也并不存储所有的右下行路，节省了时间和空间。由矩阵中1的出现情况可见，本算法所需的空间和时间都远小于O（mn）
结束语
本文给出了一个与模式匹配不同的，具有若干应用的，串的最大匹配算法，该算法已经在机器上实现，达到了预期的效果。本文仅讨论权值恒为1的情况，对于权值任意的情形不难由此得到推广。
C语言
#include<stdio.h>
#include<string.h>
void getnext(int next[],char s[],int l)
{
int i=1,j=0;
next[1]=0;
while(i<l)
{
if(j==0 || s[i]==s[j])
{
i++;j++;
next[i]=j;
}
else
j=next[j];
}
}
int KMP(char s1[],char s2[],int l1,int l2,int next[])
{
int i,j;
i=j=1;
while(i<=l1 && j<=l2）
{
if(j==0||s1[i]==s2[j])
{
i++;j++;
}
else
j=next[j];
}
if(j>l2）
return(i-l2）；
return 0;
}
int main()
{
int next[10001],ans,l1,l2;
char s1[10001],s2[10001];
scanf("%s",s1+1）；
scanf("%s",s2+1）；
l1=strlen(s1+1）；
l2=strlen(s2+1）；
getnext(next,s2,l2）；
ans=KMP(s1,s2,l1,l2,next);
if(ans!=0)
printf("%d\n",ans);
else
printf("No!\n");
system("pause");
return 0;
}
算法实现
var next:array [1 ..1000001] of longint;
s,t:ansistring;
procedure get_next(t:ansistring);
var j,k:integer;
begin
j:=1; k:=0;
while j<length(t) do
begin
if (k=0) or (t[j]=t[k]) then
begin
inc(j);
inc(k);
next[j]:=k;
end
else k:=next[k];
end;
end;
function index(s:ansistring;t:ansistring):longint;
var i,j:longint;
begin
get_next(t);
index:=0;
i:=1; j:=1;
while (i<=length(s))and(j<=length(t)) do
begin
if (j=0)or(s[i]=t[j]) then
begin
inc(i);
inc(j);
end
else j:=next[j];
if j>length(t) then index:=i-length(t);
end;
end;
begin
readln(s);
readln(t);
writeln(index(s,t))
end.
播放器
K-multimedia player的缩写  来自韩国的影音全能播放器，与Mplayer一样从linux平台移植而来的Kmplayer（简称KMP)几乎可以播放您系统上所有的影音文件。通过各种插件扩展KMP可以支持层出不穷的新格式。强大的插件功能，直接从Winamp继承的插件功能，能够直接使用winamp的音频 ，输入，视觉效果插件，而通过独有的扩展能力，只要你喜欢，可以选择使用不同解码器对各种格式进行解码。
KMPlayer The Professional Media Player! 
它支持 Winamp 2/5 的输入、常规、DSP、视觉效果、媒体库插件。无须注册表支持直接调用 Directshow 滤镜！FFdshow 的视觉特效系统~超强的 GUI 界面~安装电视卡后可以直接代替原软件直接收看电视~支持播放 DVD/VCD 以及绝大多数电脑的媒体文件（AⅥ 支持 Xvid/DivX/3vid/H264 OGG/OGM/MKV 容器/AC3/DTS 解码~Monkey Audio 解码~）强烈推荐！此播放器除了会将自己的配置信息写入注册表外绝对绿色~ 
KMplayer内置目前常见的所有解码器，包括real,QT等。
另外KMplayer安装版也是目前很少见的检查流氓软件的安装方式，如果一旦有恶意的汉化小组汉化并捆绑了流氓软件。该安装程序自动会识别，并作出提示，建议用户不要安装，虽然不是特别准确，但KMplayer的无广告及第三方插件的特点使其深受好评。
目前韩国官方已经在Kmplayer里自带了中文字库，只要用户是中文系统，软件就会自动识别，十分方便。
KMP版本：
KMPlayer3.3.0.32