回文自动机( I Love Palindrome String)

回文自动机( I Love Palindrome String)

题目描述
You are given a string S=s1s2..s|S| containing only lowercase English letters. For each integer i∈[1,|S|] , please output how many substrings slsl+1…srsatisfy the following conditions:
 ∙ r−l+1 equals to i.
 ∙ The substring slsl+1…sr is a palindrome string.
 ∙ slsl+1…s⌊(l+r)/2⌋ is a palindrome string too.
|S| denotes the length of string S.
A palindrome string is a sequence of characters which reads the same backward as forward, such as madam or racecar or abba. 

 

输入
There are multiple test cases.
Each case starts with a line containing a string S(1≤|S|≤3×10 5 ) containing only lowercase English letters.
It is guaranteed that the sum of |S| in all test cases is no larger than 4×10 6 .

 

输出
For each test case, output one line containing |S| integers. Any two adjacent integers are separated by a space.

 

样例输入

复制样例数据

abababa
样例输出
7 0 0 0 3 0 0

 

回文自动机:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int MAX = 3e5+100;
const int ALP = 26;
struct Palindromic_Tree {
    int son[MAX][ALP];
    int fail[MAX];
    int cnt[MAX];
    int num[MAX];
    int len[MAX];
    vector<int> to[MAX];
    int S[MAX];
    int last;
    int n;
    int p;
 
    int newnode(int l) {
        memset(son[p], 0, sizeof(son[p]));
        cnt[p] = 0;
        num[p] = 0;
        len[p] = l;
        return p++;
    }
 
    void init() {
        p = 0;
        newnode(0);
        newnode(-1);
        last = 0;
        n = 0;
        S[n] = -1;
        fail[0] = 1;
        to[1].push_back (0);
    }
 
    int get_fail(int x) {
        while (S[n - len[x] - 1] != S[n]) x = fail[x];
        return x;
    }
 
    void add(int c) {
        c -= 'a';
        S[++n] = c;
        int cur = get_fail(last);
        if (!son[cur][c]) {
            int now = newnode(len[cur] + 2);
            fail[now] = son[get_fail(fail[cur])][c];
            to[son[get_fail(fail[cur])][c]].push_back (now);
            son[cur][c] = now;
            num[now] = num[fail[now]] + 1;
        }
        last = son[cur][c];
        cnt[last]++;
    }
    void count() {
        for (int i = p - 1; i >= 0; i--) cnt[fail[i]] += cnt[i];
    }
} xxx;
const int maxn = 3e5+100;
int ans[maxn];
bool vis[maxn];
void dfs(int u) {
    if(vis[(xxx.len[u]+1)/2]) {
        ans[xxx.len[u]]+=xxx.cnt[u];
    }
    if(xxx.len[u]>=0)  vis[xxx.len[u]]=1;
    for( auto v:xxx.to[u]) {
        dfs (v);
    }
    if(xxx.len[u]>=0)  vis[xxx.len[u]]=0;
    return;
}
 
int main()
{
    string s;
    while (cin>>s) {
        int siz = s.length ();
        for(int i=0;i<=siz;i++) {
            xxx.to[i].clear ();
            ans[i]=0;
        }
        xxx.init ();
        for(auto x : s) xxx.add (x);
        xxx.count ();
        dfs (1);
        ans[1]=siz;
        for(int i=1;i<=siz;i++) {
            printf ("%d",ans[i]);
            if(i!=siz) printf (" ");
            else printf ("\n");
        }
    }
}

回文自动机+dfs;

1
DFS

回溯维护不同长度回文串个数。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值