• HDU 5157(回文树)


    传送门

    题面:
     

    Harry got a string T, he wanted to know the number of T’s disjoint palindrome substring pairs. A string is considered to be palindrome if and only if it reads the same backward or forward. For two substrings of T:x=T[a1…b1],y=T[a2…b2]T:x=T[a1…b1],y=T[a2…b2](where a1 is the beginning index of x,b1x,b1 is the ending index of x. a2,b2a2,b2 as the same of y), if both x and y are palindromes and b1<a2 or b2<a1b1<a2 or b2<a1 then we consider (x, y) to be a disjoint palindrome substring pair of T.

    Input

    There are several cases. 
    For each test case, there is a string T in the first line, which is composed by lowercase characters. The length of T is in the range of [1,100000].

    Output

    For each test case, output one number in a line, indecates the answer.

    Sample Input

    aca
    aaaa

    Sample Output

    3
    15
    

    Hint

    For the first test case there are 4 palindrome substrings of T.
    They are:
    S1=T[0,0]
    S2=T[0,2]
    S3=T[1,1]
    S4=T[2,2]
    And there are 3 disjoint palindrome substring pairs.
    They are:
    (S1,S3) (S1,S4) (S3,S4).
    So the answer is 3.

    题意:

        给你一个字符串,让你求不相交的回文子串的对数。

    题目分析:

        回文树num数组的运用。(又学到了骚操作了呢)

        因为我们要处理的是不相交的回文串,因此对于一个长度为len的字符串,倘若在第i个位置,我们知道了字符串[0,i]中回文子串的个数size1,又知道字符串[i+1,len-1]中回文子串的个数size2,那么当前位置对答案的贡献则是size1*size2。

        而此时我们需要求的每一个位置的回文子串的个数,我们可以通过回文树中的num数组(即表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数)去解决。

        我们只需要先正向建立回文树,先统计出对于每一个字符的num[i],并统计前缀和,最后再反向建树,最后直接将每一部分的相乘并统计答案即可。

    代码:

    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    typedef long long ll;
    struct PAM{//回文树
        int next[maxn][26],fail[maxn],cnt[maxn],len[maxn],num[maxn],S[maxn];
        int id,last,n;
        int newnode(int x){
            for(int i=0;i<26;i++){
                next[id][i]=0;
            }
            cnt[id]=0;
            len[id]=x;
            num[id]=0;
            return id++;
        }
        void init(){
            id=0;
            newnode(0);
            newnode(-1);
            fail[0]=1;
            last=n=0;
            S[n]=-1;
        }
        int getfail(int x){
            while(S[n-len[x]-1]!=S[n]) x=fail[x];
            return x;
        }
        int Insert(int c){
            S[++n]=c;
            int cur=getfail(last);
            if(!next[cur][c]){
                int now=newnode(len[cur]+2);
                fail[now]=next[getfail(fail[cur])][c];
                next[cur][c]=now;
                num[now]=num[fail[now]]+1;
            }
            last=next[cur][c];
            return num[last];
        }
    }pam;
    ll sum[maxn];
    char str[maxn];
    int main()
    {
        while(~scanf("%s",str+1)){
            int len=strlen(str+1);
            pam.init();
            sum[0]=0;
            for(int i=1;i<=len;i++){//正向建树并统计前缀和
                sum[i]=sum[i-1]+pam.Insert(str[i]-'a');
            }
            ll res=0;
            pam.init();
            for(int i=len;i>=1;i--){//反向建树并统计答案
                res+=sum[i-1]*pam.Insert(str[i]-'a');
            }
            printf("%lld
    ",res);
        }
    }
    
  • 相关阅读:
    sdk 今日头条_字节跳动又一Android开源力作!全新视频动画特效SDK
    Android播放透明视频(转载)
    git remote: warning: suboptimal pack
    'gitclone报错fatal:protocolerror:badpackheader'
    解决 Maven 无法下载 fastdfs-client-java 依赖。
    教我兄弟学Android逆向12 编写xposed模块
    教我兄弟学Android逆向11 动态调试init_array
    CommunicationsException
    使用css给table表格表头添加斜线(斜线表格)
    [SAA + SAP] 28. Monitoring
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007203.html
Copyright © 2020-2023  润新知