[学习笔记]线性代数 - 回文自动机

题目大意:每次往左/右加一个字符,问回文串和本质不同的回文串数量。
回文自动机模板题。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
#define las(x) ((x)?las1:las0)
const int N=410000,SIG=30;
struct PAM{
    int node_cnt,dpt[N],len[N],fa[N],ch[N][SIG],s[N],L,R,las0,las1,tot;lint ans;
    inline int new_node(int l,int x=0) { return len[x=++node_cnt]=l,memset(ch[x],0,sizeof ch[x]),fa[x]=dpt[x]=0,tot++,x; }
    inline int init(int m) { return node_cnt=-1,new_node(0),new_node(-1),L=m+5,R=L-1,fa[0]=1,ans=tot=las(0)=las(1)=0,0; }
    inline int find(int x,int d)
    {
        if(d) while(s[R]!=s[R-len[x]-1]) x=fa[x];
        else while(s[L]!=s[L+len[x]+1]) x=fa[x];
        return x;
    }
    inline int extend(int c,int d)
    {
        if(d) s[++R]=c;
        else s[--L]=c;
        int x=find(las(d),d);
        if(!ch[x][c])
        {
            int y=new_node(len[x]+2);
            fa[y]=ch[find(fa[x],d)][c];
            dpt[y]=dpt[fa[y]]+1;
            if(len[y]==R-L+1) las(d^1)=y;
            ch[x][c]=y;
        }
        return ans+=dpt[las(d)=ch[x][c]],0;
    }
}p;
char tp[10],qwq[10];
int main()
{
    int m=inn();p.init(m);
    while(m--)
        scanf("%s%s",tp+1,qwq+1),
        p.extend(qwq[1]-'a'+1,tp[1]=='r'),
        printf("%lld %d\n",p.ans,p.tot);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/84893535
今日推荐