HDU - 5157 :Harry and magic string (回文树)

Posted hua-dong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 5157 :Harry and magic string (回文树)相关的知识,希望对你有一定的参考价值。

Sample Input

aca
aaaa
Sample Output
3
15
 

题意: 多组输入,每次给定字符串S(|S|<1e5),求多少对不相交的回文串。

思路:可以用回文树求出以每个位置结尾的回文串数,那么累加得到前缀和; 倒着再做一遍得到每个位置为开头的回文串数,乘正向求出的前缀和即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=100010;
struct PAT
{
    struct node{
        int len,num,fail,son[26];
    }t[maxn];
    int last,n,tot,s[maxn];
    void init()
    {
        memset(t,0,sizeof(t));
        tot=last=1; n=0;
        t[0].len=0; t[1].len=-1;
        t[0].fail=t[1].fail=1;
        s[0]=-1;
    }
    int add(int c){
        int p=last; s[++n]=c;
        while(s[n]!=s[n-1-t[p].len]) p=t[p].fail;
        if(!t[p].son[c]){
            int v=++tot,k=t[p].fail;
            while(s[n]!=s[n-t[k].len-1]) k=t[k].fail;
            t[v].fail=t[k].son[c];
            t[v].len=t[p].len+2;
            t[v].num=t[t[v].fail].num+1;
            t[p].son[c]=v;
        }
        last=t[p].son[c];
        return t[last].num;
    }
}T;
ll ans,sum[maxn];char c[maxn];
int main()
{
    while(~scanf("%s",c+1)){
        int N=strlen(c+1);
        T.init(); ans=0;
        rep(i,1,N) sum[i]=sum[i-1]+T.add(c[i]-a);
        T.init();
        rep2(i,N,1) ans+=sum[i-1]*T.add(c[i]-a);
        printf("%lld
",ans);
    }
    return 0;
}

 

以上是关于HDU - 5157 :Harry and magic string (回文树)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5154 Harry and Magical Computer 拓扑排序

hdu 5067 Harry And Dig Machine

Harry Potter and the Hide Story(hdu3988)

HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)

HDU 5069 Harry And Biological Teacher(AC自动机+线段树)

Dijstra堆优化HDU 3986 Harry Potter and the Final Battle