POJ 2406 Power Strings 解題報告(雜湊)
阿新 • • 發佈:2018-12-24
Power Strings
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.
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
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; } } } }