牛客練習賽57D(manacher||迴文自動機)

題目鏈接:https://ac.nowcoder.com/acm/contest/3781/D

思路:處理出前後綴最長迴文串,可以用manacher或者回文自動機

迴文自動機:

#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=2e5+8;
char s[N];
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];
    char s[N];
    int num,last,ds[N];
    void init()
    {
        last=0;num=1;
        tr[0].init();
        tr[1].init(-1);
        tr[0].fail=1;
        REW(ds,0);
    }
    int getfail(int x,int n)
    {
        while(s[n-tr[x].len-1]!=s[n]) x=tr[x].fail;
        return x;
    }
    void extend(int x,int n)
    {
        int cur=getfail(last,n);
        int now=tr[cur].son[x];
        if(!now)
        {
            now=++num;
            tr[now].init();
            ds[n]=tr[now].len=tr[cur].len+2;
            tr[now].fail=tr[getfail(tr[cur].fail,n)].son[x];
            tr[cur].son[x]=now;
        }
        if(n) ds[n]=max(ds[n],ds[n-1]);
        tr[now].siz++;
        last=now;
    }
}A,B;
int main()
{
    cin.tie(0);
    cout.tie(0);
    ss(s);
    strcpy(A.s,s);
    int ans=0;
    int l=strlen(s);
    A.init();B.init();
    FOR(i,0,l-1) A.extend(A.s[i]-'a',i),B.s[i]=s[l-i-1];
    FOR(i,0,l-1) B.extend(B.s[i]-'a',i);
    FOR(i,0,l-2) ans=max(ans,A.ds[i]+B.ds[l-i-2]);
    cout<<ans<<endl;
    return 0;
}

 

manacher:

#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=2e5+8;
char a[N],b[N*2];
int d[N*2],dd[N],ddd[N];
int man()
{
    int ll=strlen(a),l=0;
    b[l++]='#';
    FOR(i,0,ll-1) b[l++]=a[i],b[l++]='#';
    int id=0,mx=0,qw,ans=0;
    FOR(i,1,l-2)
    {
        if(mx>i)  d[i]=min(d[2*id-i],mx-i);
        else  d[i]=1;
        while(b[i-d[i]]==b[i+d[i]]&&i+d[i]<l)  d[i]++;
        if(i+d[i]>mx) mx=i+d[i],id=i;
        dd[i/2+(d[i]-2)/2]=max(dd[i/2+(d[i]-2)/2],d[i]-1);
        qw=i/2-(d[i]-2)/2;
        if(!(i&1)) qw--;
        ddd[qw]=max(ddd[qw],d[i]-1);
    }
    FOR(i,1,ll-1) ddd[i]=max(ddd[i],ddd[i-1]-2);
    FOL(i,ll,0) ddd[i]=max(ddd[i],ddd[i+1]);
    FOL(i,ll,0) dd[i]=max(dd[i],dd[i+1]-2);
    FOR(i,1,ll-1) dd[i]=max(dd[i],dd[i-1]);
    FOR(i,0,ll-2) ans=max(ans,dd[i]+ddd[i+1]);
    return ans;
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    ss(a);
    cout<<man()<<endl;
    return 0;
}

 

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