如果要学习KMP的话,我推荐2篇博客,我觉得非常棒
1:http://blog.csdn.net/v_july_v/article/details/7041827
2:http://www.matrix67.com/blog/archives/115
下面是一些KMP类题(不定期更新):
POJ3461
题目链接:http://poj.org/problem?id=3461
这题就是KMP算法裸题,直接代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int next[10005];
char p[10005],s[1000005];
void getnext(char *t,int *next)
{
int len=strlen(t);
int i=0,j=-1;
next[0]=-1;
while(i<len)
{
if(j==-1||t[i]==t[j])
{
if(t[i]==t[j]) j=next[j];
else
next[++i]=++j;
}
else
j=next[j];
}
}
int kmp(char *a,char *b)
{
int i=0,j=0,ans=0;
int alen=strlen(a);
int blen=strlen(b);
while(i<alen)
{
if(j==-1||a[i]==b[j])
{
++i;
++j;
}
else
j=next[j];
if(j==blen) ans++;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",p,s);
getnext(p,next);
printf("%d\n",kmp(s,p));
}
return 0;
}
POJ 2406(求最小循环节的个数)
KMP的next表示模式串如果第i位(设str[0]为第0位)与文本串第j位不匹配则要回到第next[i]位继续与文本串第j位匹配。则模式串第1位到next[n]与模式串第n-next[n]位到n位是匹配的。所以思路和上面一样,如果n%(n-next[n])==0,则存在重复连续子串,长度为n-next[n]。
例如:a b a b a b
next: -1 0 0 1 2 3 4
next[n]==4,代表着,前缀abab与后缀abab相等的最长长度,这说明,ab这两个字母为一个循环节,长度=n-next[n];
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int next[1000005];
char a[1000005];
void getnext(char *p,int len)
{
int j=0,k=-1;
next[0]=-1;
while(j<len)
{
if(k==-1||p[j]==p[k])
{
next[++j]=++k;
}
else
k=next[k];
}
}
int main()
{
while(scanf("%s",a)!=EOF)
{
if(a[0]=='.') break;
int len=strlen(a);
getnext(a,len);
if(len%(len-next[len])==0)
printf("%d\n",len/(len-next[len]));
else
printf("1\n");
}
return 0;
}