kmp算法

1.引入next数组

数组含义:对于一个字符串ababaab 

next[0],next[1],next[2],next[3]...分别表示a,ab,aba,abab,的最长前缀和最长后缀相同的长度他们是

    ,    ,a  ,ab,

值分别为 -1,-1,0,1     -1表示不存在,0表示存在长度为1,2表示存在长度为3

2.求一个字符串的next数组

对于一个字符串

        ababab      他有相同的地方就是第一个a等于第三个a,第二个b等于第四个b。。。。。

                               此时他的next[5]=3;

                            现在增加一个字母,只要检测他是否等于str[k+1]即是str[1]

                            若是,k在原来基础上+1

                            若不等于 

                             a   a   b  a   a  b c   d  e   a  a  b   a   a   [f]

                            只能在前缀里找,对前缀求next[],得出最长前后缀相同的长度。然后double的前缀就和

                            []前面的字母相同,现在只要str[k+1]==f就找到了最长的。

                               若还是不等对doule的前缀再找前缀。

程序实现

void cal_next(char *str, int *next, int len)

{int i,k;

next[0]=0;

k=-1;

for(i=1;i<len;i++){

while(k>-1&&str[k+1]!=str[i])

{k=next[k];}

if(str[k+1]==str[i])

{k=k+1;}

next[i]=k;

}

return 0;

}

3.通过next函数实现kmp算法

int KMP(char *str, int slen, char *ptr, int plen){

int *next = new int[plen];

cal_next(ptr, next, plen);//计算next数组

int k = -1; for (int i = 0; i < slen; i++) //k初始化为-1

{ while (k >-1&& ptr[k + 1] != str[i])//ptr和str不匹配,且k>-1(表示ptr和str有部分匹配)

k = next[k];//往前回溯

if (ptr[k + 1] == str[i]) //首先k=-1在这里变成0;如果一直相等不做处处理,知道出现两种情况1.不相等了

k = k + 1; //不相等了,则next[k]表示是后缀有几个已经在str里然后直接赋值给k,再此基础上继续 2.ptr遍历完了

if (k == plen-1)//说明k移动到ptr的最末端

{ //cout << "在位置" << i-plen+1<< endl;

k = -1;//重新初始化,寻找下一个

//i = i - plen + 1;//i定位到该位置,外层for循环i++可以继续找下一个(这里默认存在

两个匹配字符串可以部分重叠),感谢评论中同学指出错误。

return i-plen+1;//返回相应的位置 } }

return -1; }

















                          

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页