Power Strings
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 32810 | Accepted: 13670 |
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.
Source
解题报告:正常做法是用KMP,求失败指针什么的。我这里直接用字符串哈希和矩阵快速幂搞定了。
首先从小到大枚举可能的重复串的长度,使用矩阵快速幂递推最后一位的哈希值,与实际计算的哈希值比较,相同则说明当前子串为最小的重复串,此时n最大。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <cassert>
using namespace std;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define bit(n) (1LL<<(n))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
freopen("in.txt", "r", stdin);
#endif // ACM
work();
}
void nextInt(int & x)
{
char ch;
while(ch = getchar(), isdigit(ch) == false);
x = 0;
while(x = 10 * x + ch - '0', ch = getchar(), isdigit(ch) == true);
}
/*****************************************华丽分割线**********************************************/
ULL powULL(ULL a, int b)
{
ULL ret = 1;
while(b)
{
if(b&1)
ret *= a;
a *= a;
b /= 2;
}
return ret;
}
struct Matrix
{
ULL a[2][2];
Matrix()
{
memset(a, 0, sizeof(a));
}
ULL* operator[](int i)
{
return a[i];
}
Matrix operator*(const Matrix & b) const
{
Matrix c;
ff(i, 2) ff(j, 2) ff(k, 2)
c[i][j] += a[i][k] * b.a[k][j];
return c;
}
};
Matrix powMatrix(Matrix a, int b)
{
Matrix ret;
ret[0][0] = ret[1][1] = 1;
while(b)
{
if(b&1)
ret = ret * a;
a = a * a;
b /= 2;
}
return ret;
}
template<int Size>
struct HashString
{
ULL h[Size];
void init(char * s, int len = -1)
{
if(len == -1) len = strlen(s);
fff(i, 1, len)
h[i] = h[i-1] * 29 + *s++;
}
ULL get(int sta, int len)
{
return h[sta + len] - h[sta] * powULL(29, len);
}
};
HashString<10000003> hs;
char str[1111111];
void work()
{
while(scanf("%s", str) == 1)
{
int len = strlen(str);
if(len == 1 && str[0] == '.') break;
hs.init(str, len);
fff(i, 1, len) if(len % i == 0)
{
Matrix a;
a[0][0] = a[0][1] = hs.get(0, i);
Matrix b;
b[1][0] = b[1][1] = 1;
b[0][0] = powULL(29, i);
b = powMatrix(b, len/i - 1);
a = a * b;
if(a[0][0] == hs.h[len])
{
printf("%d\n", len/i);
break;
}
}
}
}