Power Strings
|
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 38054 | Accepted: 15753 |
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.
题意:
给一个字符串a,它可以看成若干个相同的子串串联形成的,求最大串联次数n。
分析:
这题还是有一定程度的操作技巧的!
实际上,求最大的串联的次数,等价于求字符串的最小周期内包含的字符数,字符串a的周期肯定是大于等于1的,那么我用两个字符串 a 相串联,他们构成的新串为b,那么这个时候我以 b 串为 主串, a 串为 模串,当第一次匹配成功时,ANSWER = 主串 b 上所走过的字符数减去 - 原字符串 a 的长度。
其实这个是很好证明的。因为 b 串是由两个 a 串组成的,那么 b 串的最小周期内包含的字符数 == a 串最小周期内包含的字符数,刚开始a串开头与b串开头是对齐的,a串与b串是匹配成功的,那么接下来, 把 a 串向后移动一个最小周期之后,a串与b串是匹配成功的。反之,a串 经过若干字符后重新与 b 串匹配成功,那么显然,最小周期内包含的字符数 == 此时a串的开头 - b串的开头 == 主串 b 上所走过的字符数减去 - 原字符串 a 的长度。
实现代码:
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define CASE(T) int T;for(scanf("%d",&T);T--;)
const int maxn = 1000000 + 5;
char a[maxn],b[maxn << 1];
int Next[maxn];
void getNext(char x[], int m, int next[])
{
int i, j;
j = next[0] = -1, i = 0;
while(i < m)
{
while(-1 != j && x[i] != x[j]) j = next[j];
++i, ++j;
next[i] = j;
}
}
int KMP(char s[], int slen, char p[], int plen)
{
int i, j;
getNext(p, plen, Next);
i = 1, j = 0;
while(i < slen)
{
while(-1 != j && s[i] != p[j]) j = Next[j];
++i, ++j;
if(j >= plen) break;
}
return i - plen;
}
int main()
{
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%s", a))
{
if(a[0] == '.' && strcmp(a, ".") == 0) break;
int alen = strlen(a), ans;
strcpy(b,a);
strcpy(b+alen,a);
int TLen = KMP(b,alen<<1,a,alen);
ans = alen / TLen;
printf("%d\n", ans);
}
return 0;
}