zoukankan      html  css  js  c++  java
  • hdu5157 Harry and magic string 回文树

    统计一个字符串中不相交的回文串的对数。

    枚举以i为右端点的回文串,乘以在区间[i+1,n]的回文串个数,累加即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn=200100;
    const int INF=1e9+10;
    
    char s[maxn],t[maxn];
    int ls,lt;
    
    struct PalinTree
    {
        int ch[maxn][26],f[maxn];
        int n,tot,last;
        int len[maxn];
        int s[maxn];
        ll num[maxn];
        ll cnt[maxn];
        ll cnt2[maxn];
        int newnode(int l)
        {
            MS0(ch[tot]);
            len[tot]=l;
            return tot++;
        }
        void init()
        {
            tot=0;
            newnode(0);
            newnode(-1);
            n=last=0;
            s[n]=-1;f[0]=1;
            num[0]=0;num[1]=-1;
            cnt[0]=0;
            cnt2[0]=0;
        }
        int get_fail(int x)
        {
            while(s[n-len[x]-1]!=s[n]) x=f[x];
            return x;
        }
        void add(int c)
        {
            c-='a';
            s[++n]=c;
            last=get_fail(last);
            if(!ch[last][c]){
                int cur=newnode(len[last]+2);
                f[cur]=ch[get_fail(f[last])][c];
                num[cur]=num[f[cur]]+1;
                ch[last][c]=cur;
            }
            last=ch[last][c];
            cnt[n]=cnt[n-1]+num[last];
            cnt2[n]=num[last];
        }
        void build(char *str)
        {
            init();
            int ls=strlen(str);
            REP(i,0,ls-1) add(str[i]);
        }
    };PalinTree ps,pt;
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~scanf("%s",s)){
            ls=lt=strlen(s);
            REP(i,0,ls-1) t[i]=s[ls-i-1];
            ps.build(s);
            pt.build(t);
            ll ans=0;
            REP(i,1,ls-1){
                ans+=1LL*ps.cnt[i]*pt.cnt2[ls-i];
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    fatal: unable to auto-detect email address (got 'tim@newton.(none)')的解决方法
    使用git命令提示“不是内部或外部命令
    Windows系统下安装 CMake
    php与mysql的连接
    array_merge和加号的区别
    可重入锁的实现
    redis scan
    redis主丛,哨兵和集群的区别
    高并发架构系列:Redis并发竞争key的解决方案详解
    laravel上传图片
  • 原文地址:https://www.cnblogs.com/--560/p/5363237.html
Copyright © 2011-2022 走看看