KMP算法

来源:互联网 发布:最好的听书软件 编辑:程序博客网 时间:2024/06/05 07:42

KMP算法

KMP算法是一种比较高级的串匹配算法,是由Knuth、Morris和Pratt同时设计的。KMP算法-维基
普通的串匹配算法思路是将S[i]的每一位与T[0]~T[j]进行比较,如果s[i]!=T[j],则比较s[i+1]与T[0]~T[j]比较。
例1
在第一次匹配过程中,S[0]~S[3]和T[0]~T[3]匹配成功,S[4]!=T[4]匹配失败,因此有了第二次。因为在第一次中有S[1]=T[1],而T[0]!=T[1],因此有T[0]!=S[1],所以第二次是不必要的,同样第三次也是不必要的,可以直接到第四次。此进阶一次,i不回溯,j回溯到0。
进阶二:因为第一次中已经比较了S{3}=T[3],而T[0]=T[3],也因此必有S[3]=T[0],因此第四次比较可以直接比较S[4]和T[1]比较。此时是当T中含有对称性时候,T[0]对称T[3]而T[3]对应S[3],即T[0]=s[3]。因此,j可以不回溯到0,而是回溯到1。

例2

S=ababaababcb  T=ababc

新建数组next[],用于存储T的每位字符之前包含的对称性长度。
当第一次匹配时,S[4]!=T[4],此时查看T[4]的next值:next[4]=2;(计算参后)因此j回溯到2。因为S[2]S[3]=T[2]T[3],T[0]T[1]=T[2]T[3],所以S[2]S[3]=T[0]T[1],j不用回溯到0,而next对应的值便表示这个意思。
而如何计算next值呢?
next表示该位字符串前最大的对称性
0位为-1
上图的next值为{-1,0,0,1,2}

计算next方法C++代码

void GetNext(char T[],int next[]){    int i,j,len;    next[0]=-1;    for(j=1;T[j]!='\0';j++)//一次求next值    {        for(len=j-1;len>=1;len--)//对称性的最大长度为j-1,遍历长度递减        {            for(i=0;i<len;i++)//一次比较T[0]~T[len-1]与T[j-len]~T[j-1]                if(T[i]!=T[j-len+i])break;            if(i==len)            {                next[j]=len;break;            }        }        if(len<1)next[j]=0;    }}

KMP算法C++代码

int KMP(char S[],char T[]){    int i=0,j=0;    int next[80];    GetNext(T,next);    while(S[i]!='\0' && T[j]!='\0')    {        if(s[i]==T[j])        {            i++;j++;        }else{            j=next[j];            if(j==-1){i++;j++;}        }    }    if(T[j]=='\0') return (i-strlen(T)+1);//返回匹配的开始位置    else return 0;}
1 0