【BZOJ】2565最长双回文串-回文自动机

题解

这题可以马拉车水过。拿回文自动机来做一做也是一样的。
li l i 表示以第i个字符为末位置的字符串前缀的最大回文后缀。 ri r i 表示以第i个字符为首位置的字符串后缀的最大回文前缀。
那么就正着反着各做一遍回文自动机。
注意这里struct两个就好了,千万不要省空间第二遍memset用同一个数组,貌似我 O(n26) O ( n ∗ 26 ) 就TLE了。还debug了许久。
另外注意
求答案就 O(n) O ( n ) 遍历一遍取max。
写回文自动机一定要注意一点!
在增量时,一定要在建完 fail[now] f a i l [ n o w ] 以后再把 ch[last][alp] c h [ l a s t ] [ a l p ] 设为 now n o w
不然会死循环QWQ


代码

#include
using namespace std;
const int N=1e5+10;
int ans,n,l[N],r[N];
char s[N];

struct P{
    int cnt,ch[N][26],p,f[N],len[N];
    inline int new_node(int m)
{
    len[cnt]=m;return cnt++;
}

inline int get_fail(int x,int m)
{
    for(;s[m-len[x]]!=s[m+1];)
    x=f[x];
    return x;
}

inline void insert(int alp,int m,int op)
{
    p=get_fail(p,m);
    if(!ch[p][alp]){
        int now=new_node(len[p]+2);
        f[now]=ch[get_fail(f[p],m)][alp];
        ch[p][alp]=now;
    }
    p=ch[p][alp];
    if(!op) l[m+1]=len[p];
    else r[n-m]=len[p];
} 
}A,B;



int main(){
    int i;
    scanf("%s",s+1);n=strlen(s+1);
    A.new_node(0);A.new_node(-1);A.f[0]=1;
    for(i=1;i<=n;++i) A.insert(s[i]-'a',i-1,0);
    B.new_node(0);B.new_node(-1);B.f[0]=1;
    reverse(s+1,s+n+1);
    for(i=1;i<=n;++i) B.insert(s[i],i-1,1);
    for(i=1;i1]);
    printf("%d\n",ans); 
}

你可能感兴趣的:(回文自动机)