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 */
迷之AC代码

 回文串可能有奇偶之分,解决办法:

插入某字符(如#)使之全部变为奇回文串。

posted @ 2018-05-20 08:32  garage  阅读(97)  评论(0编辑  收藏  举报