zoukankan      html  css  js  c++  java
  • POJ3974 Palindrome Manacher 最长回文子串模板

    这道题可以$O(nlogn)$,当然也可以$O(n)$做啦$qwq$


    $O(nlogn)$的思路是枚举每个回文中心,通过哈希预处理出前缀和后缀哈希值备用,然后二分回文串的长度,具体的就是判断在长度范围内,前缀哈希值和后缀哈希值是否相等。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define ll unsigned long long
    #define R register int
    using namespace std;
    namespace Fread {
        static char B[1<<15],*S=B,*D=B;
        #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
        inline int g() {
            R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
            do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
        }
    }using Fread::g;
    const int B=131,N=1000010;
    int t,ans;
    ll h1[N],h2[N],p[N];
    char s[N];
    inline ll H1(int l,int r) {return h1[r]-h1[l-1]*p[r-l+1];}
    inline ll H2(int l,int r) {return h2[l]-h2[r+1]*p[r-l+1];}
    signed main() {
    #ifdef JACK
        freopen("NOIPAK++.in","r",stdin);
    #endif
        p[0]=1; for(R i=1;i<=N-10;++i) p[i]=p[i-1]*B;
        while(1) { ans=0; ++t; 
            scanf("%s",s+1); R len=strlen(s+1);
            if(len==3&&s[1]=='E'&&s[2]=='N'&&s[3]=='D') break;
            for(R i=1;i<=len;++i) h1[i]=h1[i-1]*B+(s[i]^48)+1;
            for(R i=len;i>=1;--i) h2[i]=h2[i+1]*B+(s[i]^48)+1;
            for(R p=1;p<=len;++p) {
                register int l=1,r=min(p-1,len-p);
                while(l<r) {
                    register int md=l+r+1>>1;
                    if(H1(p-md,p-1)==H2(p+1,p+md)) l=md;
                    else r=md-1;
                } ans=max(ans,l*2+1);
                l=1,r=min(p-1,len-p+1);
                while(l<r) {
                    register int md=l+r+1>>1;
                    if(H1(p-md,p-1)==H2(p,p+md-1)) l=md;
                    else r=md-1;
                } ans=max(ans,l*2);
            } printf("Case %d: %d
    ",t,ans);
        }
    }

    还有一个$Manacher$算法,可以在$O(n)$时间里解决这个问题,详见这位大佬的博客

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    #define R register int
    using namespace std;
    namespace Fread {
        static char B[1<<15],*S=B,*D=B;
        #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
        inline int g() {
            R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
            do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
        }
    }using Fread::g;
    const int N=1000010;
    char s[N<<1],str[N<<1];
    int len[N<<1],l;
    inline void getstr() {
        R k=0; str[k]='$';
        for(R i=0;i<=l;++i) str[++k]='#',str[++k]=s[i];
        str[++k]='#'; l=k;
    }
    inline void Manacher() {
        getstr(); R mx=0,id;
        for(R i=1;i<l;++i) {
            if(mx>i) len[i]=min(len[2*id-i],mx-i);//先找对称的位置,和右边界取一个min 
            else len[i]=1;//不包含直接设为1 
            while(str[i+len[i]]==str[i-len[i]]) ++len[i];//暴力匹配 
            if(len[i]+i>mx) mx=len[i]+i,id=i;//更新mx和id 
        }
    }
    signed main() {
    #ifdef JACK
        freopen("NOIPAK++.in","r",stdin);
    #endif
        R t=0; while(1) { memset(len,0,sizeof(len));  ++t;
            scanf("%s",s); l=strlen(s);
            if(l==3&&s[0]=='E'&&s[1]=='N'&&s[2]=='D') break;
            Manacher(); R ans=1; for(R i=1;i<l;++i) ans=max(ans,len[i]); 
            printf("Case %d: %d
    ",t,ans-1);
        } 
    }

    洛谷上也有$manacher$的模板,可以水一下;


    2019.06.10

  • 相关阅读:
    Android9.0/8.1/6.0 默认给系统 app 授予所有权限
    Git——处理Warning: CocoaPods is installed but broken. Skipping pod install. You appear to have CocoaPods installed but it is not working.
    Git——error: RPC failed; curl 56 LibreSSL SSL_read:报错处理
    Git——To install: sudo gem install cocoapods 报错处理
    Xcode——清除缓存相关文件
    vue —— 拉取远程仓库在本地开发
    vue —— mac中配置Node、NPM环境
    Flutter——常见报错处理
    Git——从githup上克隆下一个完整的项目操作步骤
    Git——rebase实际操作遇到的问题
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10997186.html
Copyright © 2011-2022 走看看