我们只要暴力枚举块的大小就可以了。。。
枚举的总复杂度是O(n / 1 + n / 2 + n / 3 + ...) = O(n * logn)的
何如去重呢。。。直接暴力hash再丢进set里搞定,总复杂度O(n * log2n)
1 /************************************************************** 2 Problem: 2081 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:4932 ms 7 Memory:18312 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 #include <set> 13 #include <vector> 14 15 using namespace std; 16 typedef unsigned long long ull; 17 const int N = 5e5 + 5; 18 const int base = 200191; 19 20 int n, a[N], ans; 21 ull b[N], h1[N], h2[N]; 22 vector <int> Ans; 23 vector <int> ::iterator it; 24 25 inline int read() { 26 int x = 0, sgn = 1; 27 char ch = getchar(); 28 while (ch < ‘0‘ || ‘9‘ < ch) { 29 if (ch == ‘-‘) sgn = -1; 30 ch = getchar(); 31 } 32 while (‘0‘ <= ch && ch <= ‘9‘) { 33 x = x * 10 + ch - ‘0‘; 34 ch = getchar(); 35 } 36 return sgn * x; 37 } 38 39 ull calc1(int l, int r) { 40 return h1[r] - h1[l - 1] * b[r - l + 1]; 41 } 42 43 ull calc2(int l, int r) { 44 return h2[l] - h2[r + 1] * b[r - l + 1]; 45 } 46 47 set <ull> S; 48 int calc(int sz) { 49 S.clear(); 50 for (int i = 1; i + sz - 1 <= n; i += sz) 51 S.insert(min(calc1(i, i + sz - 1), calc2(i, i + sz - 1))); 52 return (int) S.size(); 53 } 54 55 int main() { 56 int i, t; 57 n = read(); 58 for (i = 1; i <= n; ++i) a[i] = read(); 59 for (i = b[0] = 1; i <= n; ++i) b[i] = b[i - 1] * base; 60 for (i = 1; i <= n; ++i) 61 h1[i] = h1[i - 1] * base + a[i]; 62 for (i = n; i; --i) 63 h2[i] = h2[i + 1] * base + a[i]; 64 ans = 0; 65 for (i = 1; i <= n; ++i) { 66 t = calc(i); 67 if (t > ans) { 68 ans = t; 69 Ans.clear(); 70 } 71 if (ans == t) Ans.push_back(i); 72 } 73 printf("%d %d\n", ans, (int) Ans.size()); 74 for (it = Ans.begin(); it != Ans.end(); ) { 75 printf("%d", *it), ++it; 76 if (it == Ans.end()) puts(""); 77 else putchar(‘ ‘); 78 } 79 return 0; 80 }
原文:http://www.cnblogs.com/rausen/p/4328592.html