zoukankan      html  css  js  c++  java
  • BZOJ 3676(回文树模板题)

    传送门

    题面:

    3676: [Apio2014]回文串

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 3755  Solved: 1755
    [Submit][Status][Discuss]

    Description

    考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出 
    现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最 
    大出现值。 

    Input

    输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。 

    Output


    输出一个整数,为逝查回文子串的最大出现值。 

    Sample Input

    【样例输入l】
    abacaba

    【样例输入2]
    www

     

    Sample Output

    【样例输出l】
    7

    【样例输出2]
    4

    HINT

    一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。 

    在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中: 

    ● a出现4次,其出现值为4:1:1=4 

    ● b出现2次,其出现值为2:1:1=2 

    ● c出现1次,其出现值为l:1:l=l 

    ● aba出现2次,其出现值为2:1:3=6 

    ● aca出现1次,其出现值为1=1:3=3 

    ●bacab出现1次,其出现值为1:1:5=5 

    ● abacaba出现1次,其出现值为1:1:7=7 

    故最大回文子串出现值为7。 

    【数据规模与评分】 

    数据满足1≤字符串长度≤300000。

    题目分析:

        回文树模板题。首先需要了解回文树的含义

        知道了回文树的含义后,我们很明显可以发现,事实上题目中要我们求的就是长度为i的字符串的本质不同的回文字串的个数num,用num*i即为最终的答案。

        因此我们只需要将字符串建一颗回文树,之后按fail边自下而上更新一下即可

        最后只需要输出它们当中最大的。

    代码:

    #include <bits/stdc++.h>
    #define maxn 300005
    using namespace std;
    char str[maxn];
    typedef long long ll;
    struct PAM{//回文树
        int next[maxn][26],fail[maxn],len[maxn],cnt[maxn],S[maxn];
        int id,n,last;
        int newnode(int x){
            for(int i=0;i<26;i++){
                next[id][i]=0;
            }
            cnt[id]=0;
            len[id]=x;
            return id++;
        }
        void init(){
            id=0;
            newnode(0);
            newnode(-1);
            fail[0]=1;
            S[0]=-1;
            last=n=0;
        }
        int getfail(int x){
            while(S[n-len[x]-1]!=S[n]) x=fail[x];
            return x;
        }
        void Insert(int c){
            c-='a';
            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;
            }
            last=next[cur][c];
            cnt[last]++;
        }
        void getsum(){//自下向上更新
            for(int i=id-1;i>=0;i--){
                cnt[fail[i]]+=cnt[i];
            }
        }
    }pam;
    int main()
    {
        scanf("%s",str);
        pam.init();
        int len=strlen(str);
        for(int i=0;i<len;i++){
            pam.Insert(str[i]);
        }
        pam.getsum();
        ll res=0;
        for(int i=2;i<pam.id;i++){
            res=max(res,1ll*pam.len[i]*pam.cnt[i]);
        }
        cout<<res<<endl;
    }
    
  • 相关阅读:
    WPF之感触
    C# WinForm 给DataTable中指定位置添加列
    MyEclipse 8.6 download 官方下载地址
    将博客搬至CSDN
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007209.html
Copyright © 2011-2022 走看看