Palindrome Page69 哈希+二分

Palindrome Page69 哈希+二分

最大回文串还可以用马拉车算法求解,时间更优一些

分析:对于一个回文串,一共会有两种情况:

  • 长度为奇数, s [ i p , i ] = r e v e r s e ( s [ i , i + p ] ) s[i-p,i]=reverse(s[i,i+p])
  • 长度为偶数, s [ i p , i 1 ] = r e v e r s e ( s [ i , i + p 1 ] ) s[i-p,i-1]=reverse(s[i,i+p-1])

对于每一个位置 i i ,分这两种情况,二分得出以这个位置为“中心”可以最大延伸的位置。

分析二分合理性:假设中心为 i i 最大奇回文串长度为 2 k + 1 ( 0 k ) 2k+1(0\leq k) ,则对于任意的 0 x k 0\le x \le k ,中心为 i i ,长度为 2 x + 1 2x+1 的子串一定为回文串。但是对于 x > k x>k ,中心为 i i ,长度为 2 x + 1 2x+1 的子串显然不是回文串。

时间复杂度: O ( N l o g ( N ) ) O(Nlog(N))

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<queue>
#include<map>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define rep(x,a,b) for (int x=a;x<=b;x++)
#define repp(x,a,b) for (int x=a;x<b;x++)
#define W(x) printf("%d\n",x)
#define WW(x) printf("%lld\n",x)
#define pi 3.14159265358979323846
#define mem(a,x) memset(a,x,sizeof a)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int maxn=2e6+7;
const int INF=1e9;
const ll INFF=1e18;
char s[maxn];
int K=0,l,r,mid;
ull f1[maxn],p[maxn],f2[maxn];
int Hash1(int l,int r)
{
    return f1[r]-f1[l-1]*p[r-l+1];
}//正向哈希值
int Hash2(int l,int r)
{
    return f2[l]-f2[r+1]*p[r-l+1];
}//逆向哈希值
int main()
{
    while(scanf("%s",s+1)&&(strcmp(s+1,"END")!=0))
    {
        int n=strlen(s+1),ans=1;
        p[0]=1,f1[0]=f2[0]=0;
        for (int i=1;i<=n;i++)f1[i]=f1[i-1]*131+s[i]-'a'+1,p[i]=p[i-1]*131;
        for (int i=n;i>=1;i--)f2[i]=f2[i+1]*131+s[i]-'a'+1;
        rep(i,1,n)
        {
            l=0,r=i-1;
            while(l<r)
            {
                mid=(l+r+1)>>1;
                if (Hash1(i-mid,i)==Hash2(i,i+mid))l=mid;
                else r=mid-1;
            }
            ans=max(ans,2*l+1);
            l=0,r=i-1;
            while(l<r)
            {
                mid=(l+r+1)>>1;
                if (Hash1(i-mid,i-1)==Hash2(i,i+mid-1))l=mid;
                else r=mid-1;
            }
            ans=max(ans,2*l);
        }
        printf("Case %d: %d\n",++K,ans);
    }
    return 0;
}
发布了125 篇原创文章 · 获赞 8 · 访问量 9102

猜你喜欢

转载自blog.csdn.net/w_udixixi/article/details/105172703