题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599
题目大意为求字符串S有多少个子串S[l,r]满足回文串的定义,并且S[l,(l+r)/2]也满足回文串的定义。
可以直接建回文自动机,然后再统计出每种回文串的个数,然后再枚举状态,判断该状态所表示的回文串它的一半是否满足回文串的定义,判断用hash来判断即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 using namespace std; 7 typedef long long ll; 8 typedef unsigned long long ull; 9 const int maxn = 3e5 + 10; 10 ull Hash[maxn], xp[maxn]; 11 void init() { 12 xp[0] = 1; 13 for (int i = 1; i <= 3e5 + 5; i++) 14 xp[i] = xp[i - 1] * 13331; 15 } 16 ull getH(int l, int r) { 17 if (l == 0)return Hash[r]; 18 return Hash[r] - Hash[l - 1] * xp[r - l + 1]; 19 } 20 bool check(int l, int r) { 21 int len = r - l + 1; 22 int mid = l + r >> 1; 23 if (len & 1)return getH(l, mid) == getH(mid, r); 24 else return getH(l, mid) == getH(mid + 1, r); 25 } 26 ll ans[maxn], id[maxn]; 27 struct Palindromic_Tree { 28 int next[maxn][26],fail[maxn], cnt[maxn],len[maxn],S[maxn]; 29 int last, n,p; 30 int newnode(int l) { 31 for (int i = 0; i < 26; ++i) next[p][i] = 0; 32 cnt[p] = 0; 33 len[p] = l; 34 return p++; 35 } 36 void init() { 37 p = 0; 38 newnode(0); 39 newnode(-1); 40 last = 0; 41 n = 0; 42 S[n] = -1; 43 fail[0] = 1; 44 } 45 46 int get_fail(int x) { 47 while (S[n - len[x] - 1] != S[n]) x = fail[x]; 48 return x; 49 } 50 void add(int c) { 51 c -= 'a'; 52 S[++n] = c; 53 int cur = get_fail(last); 54 if (!next[cur][c]) { 55 int now = newnode(len[cur] + 2); 56 fail[now] = next[get_fail(fail[cur])][c]; 57 next[cur][c] = now; 58 } 59 last = next[cur][c]; 60 cnt[last]++; 61 id[last] = n; 62 } 63 void count() { 64 for (int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i]; 65 for (int i = 2; i < p; i++) 66 if (check(id[i] - len[i], id[i] - 1)) 67 ans[len[i]] += cnt[i]; 68 } 69 }a; 70 char s[maxn]; 71 int main() { 72 init(); 73 while (~scanf("%s", s)) { 74 int n = strlen(s); 75 Hash[0] = s[0]; 76 memset(ans, 0, sizeof(ans)); 77 for (int i = 1; i < n; i++) 78 Hash[i] = Hash[i - 1] * 13331 + s[i]; 79 a.init(); 80 for (int i = 0; i < n; i++) 81 a.add(s[i]); 82 a.count(); 83 for (int i = 1; i <= n; i++) 84 printf("%lld%c", ans[i], (i == n ? ' ' : ' ')); 85 } 86 }