天天看点

【回文树】[APIO2014]Palindromes题目链接分析代码

题目链接

分析

用回文树,求出回文串的长度和出现的次数即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 300000
#define MAXC 26
using namespace std;
char s[MAXN+10];
int n;
long long ans;
inline void Read(int &x){
    static char c;
    while(c=getchar(),c!=EOF)
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
}
void read(){
    scanf("%s",s);
    n=strlen(s);
}
namespace PalindromicTree{
int n,s[MAXN+10];
struct node{
    int cnt,len;
    node *ch[MAXC],*fail;
}tree[MAXN+10],*tcnt=tree,*last;
node *Get_fail(node *p){
    while(s[n-p->len-1]!=s[n])
        p=p->fail;
    return p;
}
void init(node *p){
    p->cnt=0;
    for(int i=0;i<MAXC;i++)
        p->ch[i]=tree;
}
void init(){
    last=tree;
    tcnt=tree;
    init(tree);
    init(++tcnt);
    tcnt->len=-1;
    tree->len=0;
    tree->fail=tcnt;
    tcnt->fail=tree;
    s[0]=-1;
    n=0;
}
void insert(char c){
    s[++n]=c-='a';
    node *cur=Get_fail(last);
    if(cur->ch[c]==tree){
        node *p=++tcnt;
        init(p);
        p->len=cur->len+2;
        p->fail=Get_fail(cur->fail)->ch[c];
        cur->ch[c]=p;
    }
    last=cur->ch[c];
    last->cnt++;
}
void Get_cnt(){
    for(node *p=tcnt;p>=tree;p--)
        p->fail->cnt+=p->cnt;
}
}
void solve(){
    for(int i=0;i<n;i++)
        PalindromicTree::insert(s[i]);
    PalindromicTree::Get_cnt();
    using namespace PalindromicTree;
    for(node *p=tcnt;p>=tree;p--)
        ans=max(ans,1ll*p->cnt*p->len);
}
int main()
{
    PalindromicTree::init();
    read();
    solve();
    printf("%lld\n",ans);
}           

继续阅读