poj2406 Power Strings

Power Strings
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 43193   Accepted: 18036

Description

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3

Hint

This problem has huge input, use scanf instead of cin to avoid time limit exceed.

Analysis

        这道题目用到好多技巧。
        通过分析,可以发现,对于非循环串,答案一定为1,对于循环串,答案=字符串长度÷最小循环节长度
        第一个技巧是最小循环节长度的寻找,通过分析不难证明,最小循环节长度=字符串总长-next[最后一个字符],其中next的含义和求法详见kmp算法的介绍(link:)
        第二个技巧是判断一个字符串是不是循环串,下图中,用黑色的表示整个字符串,不同颜色的分别表示对应位置的子串。先假设原串是循环串,绿色的是循环节,长度为l,那么首先一定满足len%l==0,其中len是原串长度。根据假设图中两个绿色的部分相等,所以红色和黄色的部分也相等。好,现在我们去掉之前所有的假设,反过来看看能推出什么。当满足len%l==0时,如果红色与黄色部分相等,则一定有两个绿色部分相等,又因为上边的蓝色部分=下边的绿色部分=下边的蓝色部分=上边的粉色部分=下边的粉色部分=······=最后绿色部分下面对应的部分,所以整个串就是以绿色部分为循环节的循环串。
       综合上述两个技巧,即可轻松AC

       ****真是费劲。。。写个题解比写代码用的时间还多

CODE

//poj2406 Power Strings kmp简单应用
#include <cstdio>
#include <cstring>
#define maxlen 1000010
using namespace std;
char s[maxlen];
int next[maxlen], len;
bool judge(int l)
{
	int i;
	if(len%l)return false;
	for(i=1;i+l<=len;i++)
		if(s[i]!=s[i+l])return false;
	return true;
}
int main()
{
	int i, j, l;
	s[0]=48;
	while(scanf("%s",s+1),s[1]!='.')
	{
		len=strlen(s)-1;
		for(i=2,j=0;i<=len;i++)
		{
			for(;j&&s[j+1]!=s[i];j=next[j]);
			if(s[j+1]==s[i])j++;
			next[i]=j;
		}
		if(judge(len-next[len])) printf("%d\n",len/(len-next[len]));
		else printf("1\n");
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值