1.Next数组
next[j]={
j=1时,0
j!=1时,最大子串长度+1,即P1P2….Pk-1==Pj-k+1….Pj-1,1<k<j,(看来j=2时是没有最大子串的,因此next[2]一定为1)
其它情况,1
}
next[j]=0说明模式串与匹配串都要后移一位
next[j]!=0说明匹配串的当前字符与next[j]匹配
next数组的下标从1开始,因此我们在模式串(T)的前面添加一个字符‘#’,初始化next[1]=0
求每个next[j](j>1)时实际上利用到上next[j-1]的值
如求next[5]时,则查看next[4]的值,如果T[4]=T[next[4]],则next[5]=next[4]+1
如果T[4]!=T[next[4]],T[4]再与next[T[next[4]]]比,如果相等,则next[5]=next[T[next[4]]]+1,如此继续,如果它的next值为0,则跳到其它情况
因此,标准算法如下:
void get_next() {unsigned int length = strlen(t);next[0]=0;next[1]=0;unsigned int i=1,j=next[1];while(i<length-1){if(j==0){i++;j=1;next[i]=1;continue;}if(t[i]==t[j]){i++;j++;next[i]=j;}else j = next[j];}}
这段代码优化一下:
scanf("%s",t+1);
t[0]=’#’;
void get_next() {unsigned int length = strlen(t);//next[0]=0;next[1]=0;unsigned int i=1,j=next[1];while(i<length-1){if(j==0||t[i]==t[j]){i++;j++;next[i]=j;}else j = next[j];}}
对于POJ3461,next数组要多求一位
要求:求出上串在下串中出现的次数
Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
Sample Output
1
3
0
#include <iostream> using namespace std; #define MAX 1000003 unsigned int next[MAX]; char s[MAX]; char t[MAX]; void get_next() {unsigned int length = strlen(t);next[0]=0;next[1]=0;unsigned int i=1,j=next[1];while(i<length){if(j==0||t[i]==t[j]){i++;j++;next[i]=j;}else j = next[j];}} unsigned int kmp(){unsigned int length = strlen(s)-1;unsigned int matLen = strlen(t)-1;if(length<matLen)return 0;unsigned int i=1,j=1,count = 0;while(i<=length){if(j==0||s[i]==t[j]){i++;j++;}else j = next[j];if(j==matLen+1){count++;j = next[j]; }}return count; }int main() {freopen("i://in.txt","r",stdin);int count;scanf("%d",&count);t[0]='#';s[0]='#';for(int i=0;i<count;i++){scanf("%s",t+1);scanf("%s",s+1);get_next();printf("%d\n",kmp());}return 0; }