zoukankan      html  css  js  c++  java
  • CodeChef Palindromeness 回文自动机

    CodeChef Palindromeness

    题意

    定义一个字符串(S)的回文指数为(f(S))

    [egin{equation} f(S)= egin{cases} 0&mbox{if $S$ is not a palindrome}\ 1&mbox{if $S$ is a palindrome and |S|=1} \ 1+f(mbox{first}~lfloor frac{|S|}{2} floor~mbox{symbols of S})&mbox{if $S$ is a palindrome and |S|>1} end{cases} end{equation} ]

    给定一个字符串(S),求它的所有子串的回文指数。

    (|S| le 10^5)

    分析

    回文自动机统计每个回文子串的出现次数,并求出(trans)指针,对每个回文子串跳(trans)指针统计答案即可。

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=5e5+10;
    char s[maxn];
    int T,n,now;
    struct PAM{
        int son[maxn][26],fail[maxn],len[maxn],cnt[maxn],trans[maxn],tot,last;
        int newnode(int x){
            ++tot;
            for(int i=0;i<26;i++) son[tot][i]=0;
           	fail[tot]=0;len[tot]=x;cnt[tot]=0;
            return tot;
        }
        void init(){
            tot=-1;newnode(0);newnode(-1);
            fail[0]=1;
            last=0;
        }
        int gao(int x){
            while(s[now-len[x]-1]!=s[now]) x=fail[x];
            return x;
        }
        void insert(){
            int p=gao(last);
            if(!son[p][s[now]-'a']){
                int tmp=son[gao(fail[p])][s[now]-'a'];
                son[p][s[now]-'a']=newnode(len[p]+2);
                fail[tot]=tmp;
                if(len[tot]<=2) trans[tot]=fail[tot];
                else{
                	tmp=trans[p];
                	while(s[now-len[tmp]-1]!=s[now]||(len[tmp]+2)*2>len[tot]) tmp=fail[tmp];
                	trans[tot]=son[tmp][s[now]-'a'];
                }
            }
            last=son[p][s[now]-'a'];
            cnt[last]++;
        }
        ll qy(){
            for(int i=tot;i>=1;i--) cnt[fail[i]]+=cnt[i];
            ll ans=0;
            for(int i=1;i<=tot;i++){
                int x=i;
                while(len[x]){
                    ans+=cnt[i];
                    int y=trans[x];
                    if(len[y]!=len[x]/2) break;
                    x=y;
                }
            }
            return ans;
        }
    }P;
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%s",s+1);
    		n=strlen(s+1);
    		P.init();
    		for(now=1;now<=n;now++){
    			P.insert();
    		}
    		printf("%lld
    ",P.qy());
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    23种设计模式-桥接模式
    23种设计模式-单列模式
    23种设计模式-迭代器模式
    23种设计模式-组合模式
    23种设计模式-备忘录模式
    23种设计模式-适配器模式
    23种设计模式-状态模式
    SVN的安装和应用
    线程、线程池
    条形码
  • 原文地址:https://www.cnblogs.com/xyq0220/p/14027463.html
Copyright © 2011-2022 走看看