zoukankan      html  css  js  c++  java
  • [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 ? '
    ' : ' '));
    85     }
    86 }
  • 相关阅读:
    【codevs1227】方格取数2(最大流费最大流-模板
    【ZJOI2008】【BZOJ1033】杀蚂蚁(占坑待填
    python基础学习1-流程控制和判断
    python基础学习1-变量定义赋值,屏幕输入输出
    Jzoj5237 最长公共子序列
    Jzoj5236 利普希茨
    [置顶] 欢迎使用CSDN-markdown编辑器
    Jzoj5235 好的排列
    Jzoj5234 外星人的路径
    Jzoj5231 序列问题
  • 原文地址:https://www.cnblogs.com/sainsist/p/11328775.html
Copyright © 2011-2022 走看看