Codechef Palindromeness and SHOI2011 double palindrome

Palindromeness

Let us define the palindromeness of a string in the following way:

  • If the string is not a palindrome, its' palindromeness is zero.
  • The palindromeness of an one-letter string is 1.
  • The palindromness of a string S of the length greater than one is 1 + "palindromeness of the string that is formed by the first [|S|/2] symbols of S".

You are given a string S. Find the sum of the palindromenesses of all the non empty substrings of S (i.e. S[i..j], where i <= j). In other words, you have to calculate the sum of palindromenesses of N * (N + 1) / 2 substrings of S, where N is the length of S.

  • 1|S|105

answer

Weng Wentao "palindrome tree and its application."

solution

\ (len_i = 1 \) special processing \ (the even half_i = \) .

CO int N=100000+10;

namespace PAM{
    int str[N],n;
    int last,tot;
    int ch[N][26],fa[N],len[N];
    int half[N],val[N],siz[N];
    
    void init(){
        memset(str,-1,sizeof str),n=0;
        last=tot=1;
        memset(ch,0,sizeof ch);
        fa[0]=fa[1]=1,len[0]=0,len[1]=-1;
        memset(siz,0,sizeof siz);
    }
    int get_fail(int x){
        while(str[n-len[x]-1]!=str[n]) x=fa[x];
        return x;
    }
    void extend(int c){
        int p=get_fail(last);
        if(!ch[p][c]){
            int cur=++tot;
            len[cur]=len[p]+2;
            fa[cur]=ch[get_fail(fa[p])][c];
            ch[p][c]=cur;
            if(len[cur]==1) half[cur]=0;
            else{
                int q=half[p];
                while(str[n-len[q]-1]!=str[n] or
                      2*(len[q]+2)>len[cur]) q=fa[q];
                half[cur]=ch[q][c];
            }
            val[cur]=1+(len[cur]/2==len[half[cur]]?val[half[cur]]:0);
        }
        last=ch[p][c];
        ++siz[last];
    }
    LL main(){
        for(int i=tot;i>=2;--i) siz[fa[i]]+=siz[i];
        LL ans=0;
        for(int i=tot;i>=2;--i) ans+=(LL)siz[i]*val[i];
        return ans;
    }
}

char str[N];

void real_main(){
    scanf("%s",str+1);
    int n=strlen(str+1);
    PAM::init();
    for(int i=1;i<=n;++i){
        PAM::str[++PAM::n]=str[i]-'a';
        PAM::extend(str[i]-'a');
    }
    printf("%lld\n",PAM::main());
}
int main(){
    for(int T=read<int>();T--;) real_main();
    return 0;
}

Double palindrome

S can be written if the WW R & lt WW R & lt form is called double s palindrome.

S length is a multiple of four, it is the same before and after the two halves of the palindrome.

For a given string, calculates the length of its longest palindromic double string.

N<=500000

yyb solution to a problem of

We found that the length of its own half of the palindrome sequence can be easily transferred.

For each node, we maintain a half to indicate the length of the longest, its length does not exceed half of that ancestor node

This way only half the length is determined to see if the current point is half, and the current length of the string is a multiple of four like

To find half of the half to jump by p on the line.

co int N=500000+10;
char s[N];
int last=1,tot=1;
int ch[N][26],fa[N]={1,1},len[N]={0,-1},half[N];

int get_fa(int x,int i){
    while(s[i-len[x]-1]!=s[i]) x=fa[x];
    return x;
}
void extend(int i){
    int p=get_fa(last,i);
    int x=ch[p][s[i]-'a'];
    if(!x){
        x=++tot;
        fa[x]=ch[get_fa(fa[p],i)][s[i]-'a'];
        len[x]=len[p]+2;
        ch[p][s[i]-'a']=x;
        if(len[x]==1) half[x]=0;
        else{
            int q=half[p];
            while(s[i-len[q]-1]!=s[i]||(len[q]+2)<<1>len[x]) q=fa[q];
            half[x]=ch[q][s[i]-'a'];
        }
    }
    last=x;
}
int main(){
    int n=read<int>();
    scanf("%s",s+1);
    for(int i=1;i<=n;++i) extend(i);
    int ans=0;
    for(int i=1;i<=tot;++i)
        if(len[half[i]]<<1==len[i]&&len[i]%4==0)
            ans=max(ans,len[i]);
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/autoint/p/11419611.html