您的位置:首页 > 其它

KMP算法的练习题(poj 3461、poj 2752、poj 2406、poj 1961)

2012-03-15 22:38 447 查看
//poj 3461 Oulipo 最简单的KMP题,找出第一个字符串在第二个字符串中出现次数。
#include<stdio.h>
#define M 1000010
char s[M],t[M];
int next[M],sum;
void getNext()//求next数组
{
		int i,j;
		next[0]=-1;
		for(i=1,j=-1;s[i];i++){
				while(j!=-1&&s[i]!=s[j+1])j=next[j];//从s[j+1]开始找与s[i]相同的字母
				if(s[j+1]==s[i])j++;
				next[i]=j;//如果找到相同字母,next[i]记录此位置,否则next[i]=next[i-1]
		}
}
void kmp()
{
		int i,j;
		sum=0;
		getNext();
		for(i=0,j=-1;t[i];i++){
				while(j!=-1&&s[j+1]!=t[i])j=next[j];//按next[j]后退找出与t[i]相同的s[j+1]
				if(s[j+1]==t[i])j++;//如果找到则向后前进
				if(!s[j+1]){//如果在t中找到完整的s
						sum++;//计数增1
						j=next[j];//按next后退
				}
		}
}
int main()
{
		int T;
		scanf("%d",&T);
		while(T--){
				scanf("%s%s",s,t);
				kmp();
				printf("%d\n",sum);
		}
		return 0;
}
//poj 2752 Seek the Name, Seek the Fame 求子串前缀跟后缀一样的各种情况
#include<stdio.h>
#include<string.h>
#define M 400010
int j,n,res[M],next[M];
char s[M];
void getNext()
{
		int i=1;
		next[0]=-1;
		for(j=-1;s[i];i++){
				while(j!=-1&&s[j+1]!=s[i])j=next[j];
				if(s[j+1]==s[i])j++;
				next[i]=j;
		}
		n=i;
}
int main()
{
		int i,num;
		while(~scanf("%s",s)){
				getNext();
				j=n-1;
				num=0;
				while(j!=-1){
						res[++num]=j+1;
						j=next[j];
				}
				for(i=num;i>0;i--)printf("%d ",res[i]);
				puts("");
		}
		return 0;
}
//poj 2406 Power Strings求子串在主串中最多叠加次数
#include<stdio.h>
#define M 1000010
int n,next[M];
char s[M];
void getNext()
{
		int i=1,j=-1;
		next[0]=-1;
		for(;s[i];i++){
				while(j!=-1&&s[j+1]!=s[i])j=next[j];
				if(s[j+1]==s[i])j++;
				next[i]=j;
		}
		n=i;
}
int main()
{
		while(scanf("%s",s),s[0]!='.'){
				getNext();
				if(n%(n-next[n-1]-1))puts("1");
				else printf("%d\n",n/(n-next[n-1]-1));
		}
		return 0;
}
//poj 1961 Period 跟上面一题几乎一样,把主串的每一种前缀当作小主串,如果小主串的子串在小主串中叠加次数大于1,输出小主串长度及叠加次数。
#include<stdio.h>
#define M 1000010
int i,n,next[M];
char s[M];
void getNext()
{
		int j=-1;
		next[0]=-1;
		for(i=1;s[i];i++){
				while(j!=-1&&s[j+1]!=s[i])j=next[j];
				if(s[j+1]==s[i])j++;
				next[i]=j;
		}
}
int main()
{
		int k=0;
		while(scanf("%d",&n),n){
				scanf("%s",s);
				printf("Test case #%d\n",++k);
				getNext();
				for(i=1;i<=n;i++)
						if(i%(i-next[i-1]-1)==0&&next[i-1]>-1)
								printf("%d %d\n",i,i/(i-next[i-1]-1));
				puts("");
		}
		return 0;
}


参考资料:

http://blog.sina.com.cn/s/blog_69c3f0410100txk7.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: