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;
}

猜你喜欢

转载自www.cnblogs.com/lalalatianlalu/p/9998269.html