poj3974 Palindrome
字符串hash二次使用
题意:求最长回文子串。
字符串长度100 0000,显然是manacher,但是这本书上写的枚举中点 + 二分,时间nlogn
我抱着试一试的心态写了个,然后就A了......15秒的时限我跑了8秒
可见数据是有多水。
代码里面有一些值需要仔细斟酌...
还有一个很坑的事:全局变量和局部变量可以重名,优先局部变量。
然后我就被这个坑了一段时间。
1 #include <cstdio> 2 #include <iostream> 3 #include <string> 4 typedef unsigned long long uLL; 5 const int P = 131, N = 1000010; 6 7 uLL Hl[N], Hr[N], powP[N]; 8 std::string c; 9 int n; 10 11 inline int min(int a, int b) { 12 return a < b ? a : b; 13 } 14 inline int max(int a, int b) { 15 return a < b ? b : a; 16 } 17 18 inline uLL getHl(int l ,int r) { 19 if(l == 0) { 20 return Hl[r]; 21 } 22 return Hl[r] - Hl[l - 1] * powP[r - l + 1]; 23 } 24 inline uLL getHr(int l, int r) { 25 if(r == n - 1) { 26 return Hr[l]; 27 } 28 return Hr[l] - Hr[r + 1] * powP[r - l + 1]; 29 } 30 31 int main() { 32 33 powP[0] = 1; 34 for(int i = 1; i < N; i++) { 35 powP[i] = P * powP[i - 1]; 36 } 37 int T = 0; 38 39 while(std::cin >> c) { 40 if(c == "END") break; 41 T++; 42 printf("Case %d: ", T); 43 n = c.size(); 44 45 Hl[0] = (int)(c[0]); 46 for(int i = 1; i < n; i++) { 47 Hl[i] = P * Hl[i - 1] + (int)(c[i]); 48 //std::cout << i << " " << Hl[i] << std::endl; 49 } 50 Hr[n - 1] = (int)(c[n - 1]); 51 for(int i = n - 2; i >= 0; i--) { 52 Hr[i] = P * Hr[i + 1] + (int)(c[i]); 53 //std::cout << i << ' ' << Hr[i] << std::endl; 54 } 55 56 //printf("%lld %lld\n", getHl(6, 8), getHr(9, 11)); 57 //std::cout << getHl(6, 8) << ' ' << getHr(9, 11) << std::endl; 58 59 int ans = 1; 60 for(int i = 0; i + 1 < n; i++) { /// 枚举中点 61 int l = 0, r = min(n - i - 1, i); 62 //printf("%d %d %d ", i, l, r); 63 while(l < r) { 64 int mid = (l + r + 1) >> 1; 65 if(getHl(i - mid, i - 1) == getHr(i + 1, i + mid)) { 66 l = mid; 67 } 68 else { 69 r = mid - 1; 70 } 71 } 72 ans = max(ans, (r << 1) | 1); 73 //printf("%d\n", r); 74 75 l = 0, r = min(i + 1, n - i - 1); 76 //printf("%d %d %d ", i, l, r); 77 while(l < r) { 78 int mid = (l + r + 1) >> 1; 79 if(getHl(i + 1 - mid, i) == getHr(i + 1, i + mid)) { 80 l = mid; 81 } 82 else { 83 r = mid - 1; 84 } 85 } 86 ans = max(ans, r << 1); 87 //printf("%d\n", r); 88 } 89 printf("%d\n", ans); 90 } 91 return 0; 92 } 93 /** 94 abcbabcbabcba 95 abacacbaaaab 96 */
回文串可能有奇偶之分,解决办法:
插入某字符(如#)使之全部变为奇回文串。