如果一个字符串正着读和倒着读是一样的,则称它是回文的。

给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。

把字符串、hash为一个unsigned long long数组里的值,求范围分、字符串可以用前缀或后者表示。
回文就是 前缀+后缀 进行运算。

a~ b ~ c,是不是回文串 == a~b的hash值 是否与 c~b的hash值相等

#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;

const int N=1000000+10;
typedef unsigned long long int ull;
ull h1[N],h2[N],p[N];
char str[N];

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

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

int main(){
    int t=1;
    while(cin>>str+1 ){
        if (strcmp(str+1,"END")==0) //结束读入
                   return 0;
       
        int n=strlen(str+1);

        p[0]=1;
        for(int i=1;i<=n;i++){
            h1[i]=h1[i-1] *131 + str[i]-'a'+1;
            p[i]=p[i-1]*131;
        }
        h2[n+1]=0;
        for(int i=n;i>=1;i--){
            h2[i]=h2[i+1] *131 +str[i]-'a'+1;
        }

        int ans=-1e8;
        //二分;
        for(int i=1;i<=n;i++){
            //先奇数长度;
            int l=0,r=min(i-1,n-i);
            while(l<r){
                int mid=l+r+1>>1;
                if(hash1(i-mid,i-1) == hash2(i+1,i+mid)) l=mid;
                else r=mid-1;
            }
            ans = max(l*2+1,ans);
            //二分偶数;
            l=0,r=min(i,n-i);
            while(l<r){
                int mid = l+r+1>>1;
                if(hash1(i-mid+1,i) == hash2(i+1,i+mid)) l=mid;
                else r=mid-1;
            }
            ans = max (2*l,ans);
        }
         printf("Case %d: %d\n",t++,ans);
    }
    return 0;
}
 posted on 2019-08-04 16:05  谁是凶手1703  阅读(219)  评论(0)    收藏  举报