BZOJ3676: [Apio2014]回文串

Posted ONION_CYC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3676: [Apio2014]回文串相关的知识,希望对你有一定的参考价值。

【题意】给定只含小写字母的字符串s,定义价值为回文子串的长度*出现次数,求最大价值。n<=3*10^5。

【算法】回文树

【题解】回文树上一个点的被访问次数是其作为最长回文子串的出现次数。

将fail边反向连接建树后,每个点的子树访问次数和就是这个回文子串的出现次数,可以dfs解决。

注意:要从-1点开始dfs才能保证到达所有点。记得开long long。

技术分享图片
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=600010;
int n,tot,len[maxn],fail[maxn],length,sz,nownode,ch[maxn][30],first[maxn],size[maxn];
ll ans=0;
struct edge{int v,from;}e[maxn];
char s[maxn];
int getfail(int x){while(s[length-len[x]-1]!=s[length])x=fail[x];return x;}
void build(){
    int y=s[++length]-a;
    int x=getfail(nownode);
    if(!ch[x][y]){
        len[++sz]=len[x]+2;
        fail[sz]=ch[getfail(fail[x])][y];
        ch[x][y]=sz;
    }
    size[ch[x][y]]++;
    nownode=ch[x][y];
}
void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
int dfs(int x){
    ll sum=size[x];
    for(int i=first[x];i;i=e[i].from){
        sum+=dfs(e[i].v);
    }
    ans=max(ans,sum*len[x]);
    return sum;
}
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    len[0]=0;fail[0]=1;
    len[1]=-1;fail[1]=1;
    length=0;
    sz=1;//!!!
    for(int i=1;i<=n;i++)build();
    insert(1,0);
    for(int i=2;i<=sz;i++){
        insert(fail[i],i);
    }
    dfs(1);//1
    printf("%lld",ans);
    return 0;
}
View Code

 

以上是关于BZOJ3676: [Apio2014]回文串的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3676: [Apio2014]回文串 回文树

[BZOJ3676][APIO2014]回文串(Manacher+SAM)

BZOJ 3676 [Apio2014]回文串(回文树)

BZOJ 3676 APIO2014 回文串

bzoj千题计划304:bzoj3676: [Apio2014]回文串

BZOJ3676 [Apio2014]回文串