Acwing139. 回文子串的最大长度(hash+二分)

题目大意:n个字符串,求每个字符串的最长子回文串。

回文串:正着读和反着读是相同。

题解:二分最长回文串的长度,hash判断是否是回文串。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ull unsigned long long
#define N 1000002
const ull base=13331;

ull f1[N],f2[N],p[N];
char s[N];
int js;
int len;

ull get_hash_f1(int l,int r)
{
    return f1[r]-f1[l-1]*p[r-l+1];
}

ull get_hash_f2(int l,int r)
{
    return f2[r]-f2[l-1]*p[r-l+1];
}

bool check(int x)
{
    for(int i=1;i+x-1<=len;i++)
    {
        int l1,r1,l2,r2;
        l1=i;r1=i+x/2;
        if(x&1){
            
        }else r1--;
        l2=i+x/2;
        r2=i+x-1;
   //   if(js==4)  cout<<x<<" "<<l1<<" "<<r1<<" "<<l2<<" "<<r2<<endl;
        if(get_hash_f1(l1,r1)==get_hash_f2(len-r2+1,len-l2+1)) return true;
    }
    return false;
}

int main()
{
    while(scanf("%s",s+1)&&strcmp(s+1,"END")!=0)
    {
        ++js;
        len=strlen(s+1);
        p[0]=1;
        memset(f1,0,sizeof(f1));
        memset(f2,0,sizeof(f2));
        for(int i=1;i<=len;i++)
        {
            f1[i]=f1[i-1]*base+(s[i]-'a'+1);
            p[i]=p[i-1]*base;
        }
       reverse(s+1,s+len+1);
       for(int i=1;i<=len;i++)
       {
           f2[i]=f2[i-1]*base+(s[i]-'a'+1);
       }
        int l,r,mid,ans;
        l=0;r=len;
        while(l<=r)
        {
            mid=(l+r)>>1;
           //if(js==4) cout<<mid<<"----- "<<l<<"----- "<<r<<endl;
            if(check(mid)) {l=mid+1;ans=mid;}
            else if(check(mid+1)){ l=mid+2;ans=mid+1;}
            else r=mid-1;
        }
        printf("Case %d: %d
",js,ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zzyh/p/14785693.html