• HDU


    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;
    }
  • 相关阅读:
    主函数main
    static关键字
    this关键字
    构造函数
    封装
    匿名对象
    java基础积累
    JAVA相关知识复习
    ORACLE数据库表空间查询
    两个日期的时间差
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10355921.html
Copyright © 2020-2023  润新知