kmp算法

来源:互联网 发布:将java类传到jsp里面 编辑:程序博客网 时间:2024/06/05 03:45


 


主要思想:当主串第i个字符与模式串第j个字符匹配
          不等是不需要回朔i指针,而是利用已经得到的
          部分匹配结果next数组,将模式串向右滑动
核心:当主串中第i个字符与模式串第j个字符匹配失败时,
      主串中第i个字符(i不回朔)应与模式串中哪个字符匹配??
      这就要构建一个next数组,来存放当匹配失败应该在匹配的位置编号

怎么定义next函数呢?
       若令next[j]=k,当匹配失败时主串中第i个字符与模式串中第j个字符
       比较不等时,仅需要将模式串向右滑动k个字符再和主串第i个字符比较就行
       此时,模式串中k-1个字符t1t2t3t4tk-1必定与主串中第i个字符之前长度为k-1
       的子串相等
      
                   0        j=1(t1与sj比较不等时,下一步进行t1与si+1的比较)
         next[j] = max      {k|1<k<j 且有 "t1t2t3tk-1" = "sj-k+1sj-k+2...si-1"}
                   0        k = 1(不存在向东子串,下一步进行t1与s1的比较)
         意思就是在模式串中是否存在一个序列与从头带此的序列相等
         相等则next值为从头带此的长度
         j       1  2  3  4  5  6  7  8

       模式串    a  b  a  a  b  c  a  c
    
       next[j]   0  1  1  2  2  3  1  2

       在模式串中,next[1] = 0,
       j = 2 b前面不存在一个子序列与从头开始的子序列相等                所以 next[2] = 1
       j = 3 a前面不存在一个子序列与从头开始的子序列相等                所以 next[3] = 1
       j = 4 a前面存在一个a长度为1的子序列与重头开始长度为1的子序列相等,所以 next[4] = 2
       j = 5 b前面存在一个长度为1的子序列a与从头时开始长度1的子序列相等,所以 next[5] = 2
       j = 6 c前面存在一个长度为2的子序列ab与重头开始长度为2的序列相等, 所以 next[6] = 3
       j = 7 a前面不存在一个子序列与从头开始的子序列相等                所以 next[7] = 1
       j = 8 c前面存一个长度为1的子序列a与从头开始的长度1的子序列相等   所以 next[8] = 2


#include <iostream>#include <string>using namespace std;int next[100];void getnext(char str[]){         int i = 1,j = 0;    next[1] = 0;    int len = strlen(str);    while(i <= len)    {        if(j == 0 || str[i] == str[j])        {            i++;            j++;            next[i] = j;        }        else        {            j = next[j];        }    }    for(i = 1; i < len; i++)    {        cout<<next[i];    }    cout<<endl;} int KMP(char S[],char str[]){    int i = 1,j = 1;    int lenS = strlen(S),lentr = strlen(str);    while(i <= lenS && j <= lentr)    {        if(S[i] == str[j] || j == 0)        {            i++;            j++;        }        else        {            j = next[j];        }    }    if(j == lentr+1)        return i - lentr + 1;    else        return -1;}int main(){    char str[20],S[100];    cin>>S+1;    cin>>str+1;    getnext(str);    int pos = KMP(S,str);    if(pos == -1)        cout<<"不存在"<<endl;    else    cout<<"位置:"<<pos<<endl;    return 0;}