zoukankan      html  css  js  c++  java
  • UESTC OJ 1999(回文树)

     

    传送门

    题面:

    也许这是唯一能阻止乐爷AK的方法( Just for Fun )

    Time Limit: 1500 MS     Memory Limit: 512 MB

    Submit Status

    一个字符串如果从前往后读和从后往前读是一样的,那么它被称为回文串。举个例子,"a","aa","appa","queryreuq"都是回文串。

    对于一个初始为空的字符串S,你可以进行以下两种操作:

    1.在S的末尾加一个小写字母。

    2.移除S的最后一个字母。

    每进行完一个操作,你需要统计S中回文串的数量。对于字符串S和整数i,j(1<=i<=j<=|S|),S[i,j]代表S中第i个字符到第j个字符构成的子串。你需要输出满足S[i,j]是回文串的(i,j)对数。

    Input

    输入包含两行。

    第一行,QQ,给出操作的次数。

    第二行,操作以一个长度为QQ的字符串给出,第i个字符Ki表示第ii次操作。

    Ki是−’或者小写英语字母('a','b',...'z')(不包括括号)。

    如果字符是‘−’,你应该移除S的最后一个字母。如果字符是小写字母,你应该在S的最后加入一个字母Ki.

    保证每次操作后字符串S的长度始终是正数。

    (1<=Q<=10000)

    Output

    一行输出Q个数,以空格隔开,第ii个整数代表第ii次操作后的答案。

    Sample input and output

    Sample Input Sample Output
    17
    qu-uer-ryr-reu-uq
    1 2 1 2 3 4 3 4 5 7 5 7 9 11 9 11 13

    题目分析:

        题目不难看出就是让我们求某个字符串中的本质不同的回文字串的数量。因此我们不难想到建一颗回文树去维护。

        之后只需要模拟加串和减串的过程,不断的建回文树维护相应的字符串即可。

    代码:

    #include <bits/stdc++.h>
    #define maxn 10005
    using namespace std;
    char str[maxn];
    int ans[maxn];
    vector<int>vec;
    struct PAM{//回文树
        int next[maxn][26],fail[maxn],S[maxn],cnt[maxn],len[maxn];
        int id,last,n;
        int newnode(int x){
            for(int i=0;i<26;i++){
                next[id][i]=0;
            }
            len[id]=x;
            cnt[id]=0;
            return id++;
        }
        void inti(){
            id=0;
            newnode(0);
            newnode(-1);
            fail[0]=1;
            n=0;
            S[n]=-1;
            last=0;
        }
        int get_fail(int x){
            while(S[n-len[x]-1]!=S[n]) x=fail[x];
            return x;
        }
        void Insert(int c){
            S[++n]=c;
            int cur=get_fail(last);
            if(!next[cur][c]){
                int now=newnode(len[cur]+2);
                fail[now]=next[get_fail(fail[cur])][c];
                next[cur][c]=now;
            }
            last=next[cur][c];
            cnt[last]++;
        }
        void Get(){
            for(int i=id-1;i>=0;i--){
                cnt[fail[i]]+=cnt[i];
            }
        }
    }pam;
    int main()
    {
        int t;
        scanf("%d",&t);
        scanf("%s",str);
        int len=strlen(str);
        vec.clear();
        memset(ans,0,sizeof(int)*len);
        for(int i=0;i<len;i++){
            pam.inti();//每经历一次操作就重新建树
            if(str[i]=='-') vec.pop_back();
            else vec.push_back(str[i]-'a');
            int siz=vec.size();
            for(int j=0;j<siz;j++){//建树
                pam.Insert(vec[j]);
            }
            pam.Get();
            for(int j=2;j<pam.id;j++){
                ans[i]+=pam.cnt[j];
            }
        }
        for(int i=0;i<len;i++){
            if(i==0) printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    [BZOJ 1552] 排序机械臂
    [BZOJ 1124][POI 2008] 枪战 Maf
    [BZOJ 1647][USACO 2007 Open] Fliptile 翻格子游戏
    [BZOJ 1592] Making The Grade路面修整
    [BZOJ 3829][POI2014] FarmCraft
    [技术] 如何正确食用cnblogs的CSS定制
    [BZOJ 1458] 士兵占领
    今天写了一个Imageloader,,AndroidStudio报了Error:Execution failed for task ':app:mergeDebugResources'. > Error: Java.util.concurrent.ExecutionException: com.Android.ide.common.process.ProcessException: 这个错误
    Http响应码代表的含义
    获取WIFI列表,在旧手机上运行就没有问题,在新手机上就怎么也获取不到WIFI列表,长度一直为0,还不报异常,很疑惑。
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007207.html
Copyright © 2011-2022 走看看