next[i]数组存放 当i不匹配时,下一次比较从next[i]开始。而数组从0开始,0就代表第一个数,1代表第二个数。
读入字符串从0开始
#include <stdio.h>
#include <string.h>
#define maxn 1000010
char a[maxn],b[maxn],next[maxn];
void get_next()
{
int k=-1;
int j=0;
next[0]=-1;
int b_len=strlen(b);
while(j<b_len)
{
if(k==-1||b[j]==b[k])
{
j++;
k++;
if(b[j]==b[k])
next[j]=next[k];
else
next[j]=k;
}
else
{
k=next[k];
}
}
}
int KMP()
{
int k=0,j=0;
int a_len=strlen(a),b_len=strlen(b);
while(j<a_len)
{
if(k==-1||a[j]==b[k])
{
j++;
k++;
}
else
{
k=next[k];
}
if(k==b_len)
{
printf("%d\n",j-k+1);
k=next[k];
}
}
}
int main()
{
scanf("%s",a);
scanf("%s",b);
get_next();
KMP();
//printf("%d",next[1]);
int len=strlen(b);
for(int i=1;i<=len;i++)
printf("%d ",next[i]);
}
读入字符串从1开始,并且next=1代表没有相匹配的,下一次从1开始。
next[i]=1代表第一个数
void get_next()
{
int j=1;
int k=0;
next[1]=0;
while(j<=n)
{
if(k==0||a[j]==a[k])
{
j++,k++;
next[j]=k;
}
else
k=next[k];
}
}
读入字符串从1开始,并且next【i】存放以i-1为结尾 从头开始 有多少个数相匹配,0代表无,1代表一个。
用于处理循环字符串问题,因为数组准确存放匹配数量。
void get_next()
{
next[1]=0;
for(int i=2,j=0;i<=n;i++)
{
while(j>0&&a[i]!=a[j+1])j=next[j];
if(a[i]==a[j+1])j++;
next[i]=j;
}
}
例题](http://poj.org/problem?id=1961)
AC代码
#include <stdio.h>
int n,next[1000010];
char a[1000010];
void get_next()
{
next[1]=0;
for(int i=2,j=0;i<=n;i++)
{
while(j>0&&a[i]!=a[j+1])j=next[j];
if(a[i]==a[j+1])j++;
next[i]=j;
}
}
void solve()
{
for(int i=2;i<=n;i++)
{
if(i%(i-next[i])==0&&i/(i-next[i])>1) // i%(i-next[i])==0为了保证循环的完整
printf("%d %d\n",i,i/(i-next[i])); //为什么(i-next[i])就是最小循环长度?
} //画图可知当前len个字符等于后len个字符时,
puts(""); //将字符串平移len个单元,会有a[len+1~2*len]=a[1~len]
} //而a[2*len+1~3*len]=a[len+1~2*len],如此下去
int main() //就是最小循环字符串
{ //i-next[next[i]]是次小循环字符串
int t=1;
while(scanf("%d",&n)&&n)
{
scanf("%s",a+1);
get_next();
printf("Test case #%d\n",t++);
solve();
}
}