zoukankan      html  css  js  c++  java
  • bzoj2565: 最长双回文串

    传送门

    今天来学回文自动机的模板吧!Achen开心地告诉自己,然后打开了一道水题。

    噫,这不是马拉车的水题嘛、、

    第一反应,马拉车,然后线段树维护第i个字母结尾的最长回文串长度

    然后其实做法应该是线性的,傻了吧,,,

    考虑马拉车的时候往后拓展,容易想到每个点第一次被拓展到的时候的那个店就是以它为结尾的最长回文串的回文中心。

    然后正反跑马拉车,枚举一下分割点统计答案即可,整体的时间复杂度也是O(n)的。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<ctime>
    const int N=2e5+7; 
    typedef long long LL;
    using namespace std;
    int ans,len,n,l[N],r[N],rad[N];
    char s[N],ss[N];
    
    void manacher(int ll[]) {
        for(int i=1,k=0,j,now=0;i<n;) {
            while(s[i-k-1]==s[i+k+1]) k++;
            rad[i]=k;
            while(now<n&&i+rad[i]>=now) {
                ll[now]=i;
                now++;
            }
            for(j=1;j<=k&&rad[i-j]!=rad[i]-j;j++) 
                rad[i+j]=min(rad[i-j],rad[i]-j);
            k=max(k-j,0);
            i+=j;
        }
    }
    
    int is(char ch) {return ch>='a'&&ch<='z';}
    
    int main() {
        scanf("%s",ss);
        int len=strlen(ss);
        s[n++]='*'; s[n++]='&';
        for(int i=0;i<len;i++) {
            s[n++]=ss[i];
            s[n++]='&'; 
        }
        s[n++]='#';
        manacher(l);
        memset(rad,0,sizeof(rad));
        for(int i=0;i<=n/2;i++) swap(s[i],s[n-i-1]);
        manacher(r);
        for(int i=1;i<n-4;i++) if(is(s[i])) {
            int a=i-r[i]+1,b=n-(i+2)-1-l[n-(i+2)-1]+1;
            ans=max(ans,a+b);
        }
        printf("%d
    ",ans); 
        return 0;
    }
    View Code

    改天来补回文自动机的做法。

    -------------------------------------------------------------------------------------

    发现其实回文自动机的代码要更短,只是跑得贼慢,大概常数比较大。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<ctime>
    const int N=1e5+7; 
    typedef long long LL;
    using namespace std;
    char s[N];
    int ans,n,last,tot,rt1,rt2,ch[N][26],len[N],fail[N],l[N],r[N],sz[N];
    
    void init() {
        len[rt1=0]=0; len[rt2=1]=-1;
        tot=1; fail[rt1]=rt2; last=rt1;
        memset(ch,0,sizeof(ch));
    }
    
    void insert(int tp,int c,int p[]) {
        int x=last,y;
        for(;(s[tp-len[x]-1]-'a')!=c;x=fail[x]);
        if(!ch[x][c]) {
            len[++tot]=len[x]+2;
            for(y=fail[x];(s[tp-len[y]-1]-'a')!=c;y=fail[y]);
            fail[tot]=ch[y][c]; // ch[x][c]=tot; fail[tot]=ch[y][c];
            ch[x][c]=tot;
        }
        last=ch[x][c];
        sz[last]++;
        p[tp]=len[last];
    }
    
    int main() {
        scanf("%s",s);
        n=strlen(s);  
        init();
        for(int i=0;i<n;i++) 
            insert(i,s[i]-'a',l);
        for(int i=0;i<=n/2;i++) swap(s[i],s[n-i-1]);
        init();
        for(int i=0;i<n;i++) insert(i,s[i]-'a',r);
        for(int i=0;i<n-1;i++) 
            ans=max(ans,r[i]+l[n-(i+1)-1]);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    uva11235 FrequentValues (ST表)
    hdu5449 Robot Dog (树形dp+倍增lca)
    [BZOJ1637][Usaco2007 Mar]Balanced Lineup
    [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理
    Luogu1119灾后重建
    [APIO2012]派遣
    [HNOI2004]宠物收养场
    [USACO14DEC] 驮运Piggy Back
    [USACO14JAN]滑雪等级Ski Course Rating
    [CODEVS3366] 矿石
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8232509.html
Copyright © 2011-2022 走看看