[2019杭电多校第二场][hdu6599]I Love Palindrome String(回文自动机&&hash)

题目链接: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 ? '\n' : ' '));
85     }
86 }

 

posted @ 2019-08-09 17:51  祈梦生  阅读(148)  评论(0编辑  收藏  举报