zoukankan      html  css  js  c++  java
  • BZOJ 3676 回文串

    题意:给你一个串,回文串有个价值,定义为回文串的长度乘以次数,求最大值

    思路:偷一份模板,附聚聚传送门

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn = 300010*2;
    const int ALP = 26;
    
    struct Palindromic_Tree{
        ///init,把每个字符add进PAM中,最后做一次Count
        int next[maxn][ALP];//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
        int fail[maxn];//fail指针,失配后跳转到fail指针指向的节点
        int cnt[maxn]; //表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后Count()函数跑一遍以后才是正确的)
        int num[maxn]; //表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
        int len[maxn];//len[i]表示节点i表示的回文串的长度(一个节点表示一个回文串)
        int S[maxn];//存放添加的字符
        int last;//指向新添加一个字母后所形成的最长回文串表示的节点。
        int n;//表示添加的字符个数。
        int p;//表示添加的节点个数。
    
        int newnode(int l){//新建节点
            for(int i=0;i<ALP;++i)next[p][i]=0;
            cnt[p]=0;num[p]=0;
            len[p]=l;
            return p++;
        }
        void init(){//初始化
            p=0;
            newnode(0);newnode(-1);
            last=0;n=0;
            S[n]=-1;//开头放一个字符集中没有的字符,减少特判
            fail[0]=1;
        }
        int get_fail(int x){//和KMP一样,失配后找一个尽量最长的
            while(S[n-len[x]-1]!=S[n])x=fail[x];
            return x;
        }
        void add(int c){
            c-='a';
            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];//和AC自动机一样建立fail指针,以便失配后跳转
                next[cur][c]=now ;
                num[now]=num[fail[now]]+1;
            }
            last=next[cur][c];
            cnt[last]++;
        }
        void Count(){
            for(int i=p-1;i>=0;--i)cnt[fail[i]]+=cnt[i];
            //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
        }
    }pam;
    
    char s[maxn];
    int main(){
        scanf("%s",s);
        int len=strlen(s);
        pam.init();
        for(int i=0;i<len;i++){
            pam.add(s[i]);
        }
        pam.Count();
        LL ans=0;
        for(int i=2;i<pam.p;i++){
            ans=max(ans,(LL)pam.len[i]*pam.cnt[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    [导入]流失
    [导入]喜欢与爱
    [导入]毕业的大学生的100条忠告
    sql 实现从右边查询制定字符出现的位置
    [导入]毕业了
    gridview 实现多字段综合查询
    Java实现图片添加水印文字(左右下角)
    python安装win32api pywin32 后出现 ImportError: DLL load failed
    Asp.net mvc 速度优化 关注Yslow(1)
    WPF 3D中如何选择模型的一部分并维护模型
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9998269.html
Copyright © 2011-2022 走看看