hdu5421(迴文自動機)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5421

思路:同時維護收尾兩個last可以實現首尾同時插入,需要注意的是當插入過後最長迴文串是當前整個字符串,要把另一個last的值設爲當前這個last的值

#pragma GCC optimize(2)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(1e9+7)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
const int N=3e5+8;
int x,n;
char a;
struct PAM{
    struct node{
        int len,fail,son[26],siz;
        void init(int _len=0){
            memset(son,0,sizeof(son));
            fail=siz=0;
            len=_len;
        }
    }tr[N];
    int s[N];
    ll num,last[2],ans,l,r;
    void init()
    {
        last[0]=last[1]=ans=0;num=1;
        l=100008,r=100007;
        tr[0].init();
        REW(s,-1);
        tr[1].init(-1);
        tr[0].fail=1;
    }
    int getfail(int x,int d)
    {
        if(d) while(s[r-tr[x].len-1]!=s[r]) x=tr[x].fail;
        else while(s[l+tr[x].len+1]!=s[l]) x=tr[x].fail;
        return x;
    }
    void extend(int x,int d)
    {
        if(d) s[++r]=x;
        else s[--l]=x;
        int cur=getfail(last[d],d);
        int now=tr[cur].son[x];
        if(!now)
        {
            now=++num;
            tr[now].init(tr[cur].len+2);
            tr[now].fail=tr[getfail(tr[cur].fail,d)].son[x];
            tr[now].siz=tr[tr[now].fail].siz+1;
            tr[cur].son[x]=now;
        }
        last[d]=now;
        if(r-l+1==tr[now].len) last[d^1]=now;
        ans+=1ll*tr[now].siz;
    }
}A,B;
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(si(n)!=EOF)
    {
        A.init();
        while(n--)
        {
            si(x);
            if(x==1) scanf(" %c",&a),A.extend(a-'a',0);
            else if(x==2) scanf(" %c",&a),A.extend(a-'a',1);
            else if(x==3) printf("%lld\n",A.num-1);
            else printf("%lld\n",A.ans);
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章