目录
字符串乘方
要求:
总时间限制: 3000ms
内存限制: 65536kB
描述:
给定两个字符串a和b,我们定义a*b为他们的连接。例如,如果a=”abc” 而b=”def”, 则a*b=”abcdef”。 如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a^0=””(空字符串),a^(n+1)=a*(a^n)。
输入:
每一个测试样例是一行可打印的字符作为输入,用s表示。s的长度至少为1,且不会超过一百万。最后的测试样例后面将是一个点号作为一行。
输出:
对于每一个s,你应该打印最大的n,使得存在一个a,让s=a^n
样例输入:
abcd aaaa ababab .
样例输出:
1 4 3
思路分析:
这个题目相比于之前的挤奶网格的题目而言就简单多了. 目标还是求一个一维字符串的最小覆盖,但是此处的最小覆盖的要求是必须要包在原字符串内部,不能有多余的部分,这一点是由题目中乘方运算所定义的.
所以在我们每次求出len-next[len]之后,需要检查是否其结果可以整除原字符串长度len,如果可以整除,结果就是len/(len-next[len]),否则结果就是1.
最终代码:
#include<iostream>
#include<cstring>
using namespace std;
void kmp(char *s, int *next, int len){
int k1=-1;
int k2=0;
next[0]=-1;
while(k2!=len){
while(k1>=0&&s[k1]!=s[k2]){
k1=next[k1];
}
k1++;
k2++;
next[k2]=k1;
}
}
int main(){
char s[1000000];
while(scanf("%s",s)&&s[0]!='.'){
int len=strlen(s);
int next[len+1];
kmp(s,next,len);
int ans=len-next[len];
printf("%d\n",len%ans==0?len/ans:1);
}
}