POJ 2406 - Power Strings

5 篇文章 0 订阅

 

题目地址: http://poj.org/problem?id=2406

 

KMP 。

 

NEXT 数组的扩展运用。

 

求字符串的最小循环节。(反过来说,就是求最小覆盖子串:len-next[len])

 

我们判断 NEXT [ LEN ]  就行了,可以得到字符串是否重复出现。如果不重复出现,循环节为1。否则:

 

1. 如果重复出现的两部分,存在重叠,那么循环节一定是len / (len - next[len])。即 len / [非重复部分的长度]。

 

     当然,必须能够整除,比如ababab,重复部分为ab,6%2。而不能够整除时,比如ababa则不行,重复部分为a,5%2。(具体证明自己想)

 

2. 如果不重叠,假如两端重复刚好各占原字符串的一半,那么也是len / (len - next[len]),比如abcabc。

 

3. 否则循环节为1,比如abcdabc。

 

#include<cstdio>

const int MAXN = 1000100;
int nxt[MAXN];
int get_next(char *ptr){
	int i,j;
	nxt[0]=0;
	for(i=1;ptr[i];i++){
		j=nxt[i-1];
		while(ptr[i]!=ptr[j] && j)
			j=nxt[j-1];
		nxt[i]=ptr[i]==ptr[j]?j+1:0;
	}
	return i; 
}

char s[MAXN];

int main(){
	int i,len;
	while(gets(s)){
		if(s[0]=='.' && !s[1]) break;
		len=get_next(s);
		if(len%(len-nxt[len-1])==0)
			printf("%d\n",len/(len-nxt[len-1]));
		else puts("1");
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值