Palindrome--POJ3974

【题目概述】如果一个字符串正着读和倒着读是一样的,则称它是回文的。给定一个长度为N的字符串S,求它的最长回文子串。

分为两类:

1.奇回文串A【1~M】,长度M为奇数,并且A【1~M/2+1】=reverse(A【M/2+1~M】),它的中心是一个字符。其中reverse(A)表示把字符串A倒过来。

2.偶回文串B【1~M】,长度M为偶数,且B【1~M/2】=reverse(B【M/2+1~M】),它的中心点是两个字符之间的夹缝。

于是,我们正反各求一次哈希,P取131或13331,M取264,也就是直接用unsigned long long类型存储这个hash值。

###正着求一次哈希值

1 ull H1(int i,int j){
2     return f1[j]-f1[i-1]*p[j-i+1];
3 }

###倒着求一次哈希值

1 ull H2(int i,int j){
2     return f2[i]-f2[j+1]*p[j-i+1];
3 }

###注意读入的写法,遇到END结束。

1 while(scanf("%s",s+1)&&(s[1]!='E'))

###预处理出p的各个次方

1     p[0]=1;
2     for(int i=1;i<=N;i++)
3     p[i]=p[i-1]*P;

枚举回文子串的中心位置i(1~N),看从这个中心位置出发向左右两侧最长可以扩展出多长的回文串。利用二分答案的思想,二分长度,再以中间点i计算长度为mid的两个子串的哈希值,如果相等,调整左指针,否则调整右指针。

在枚举过的所有中心位置对应的奇、偶回文子串长度中取max就是整道题目的答案,时间复杂度为O(NlogN)。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ull unsigned long long
 6 using namespace std;
 7 const int N=1000010,P=131;
 8 char s[N];
 9 ull f1[N],f2[N],p[N];
10 ull H1(int i,int j){
11     return f1[j]-f1[i-1]*p[j-i+1];
12 }
13 ull H2(int i,int j){
14     return f2[i]-f2[j+1]*p[j-i+1];
15 }
16 int main(){
17     int id=0;
18     p[0]=1;
19     for(int i=1;i<=N;i++)
20     p[i]=p[i-1]*P;
21     while(scanf("%s",s+1)&&(s[1]!='E')){
22         ++id;
23         int ans=0,len=strlen(s+1);
24         for(int i=1;i<=len;i++) f1[i]=f1[i-1]*P+s[i];
25         for(int i=len;i;i--)    f2[i]=f2[i+1]*P+s[i];
26         for(int i=1;i<=len;i++){
27             int l=1,r=min(i-1,len-i);
28             while(l<r){
29                 int mid=(l+r+1)>>1;
30                 if(H1(i-mid,i-1)==H2(i+1,i+mid)) l=mid;
31                 else r=mid-1;
32             }
33             ans=max(l*2+1,ans);
34             l=1,r=min(i-1,len-i+1);
35             while(l<r){
36                 int mid=(l+r+1)>>1;
37                 if(H1(i-mid,i-1)==H2(i,i+mid-1)) l=mid;
38                 else r=mid-1;
39             }
40             ans=max(l*2,ans);
41         }
42         printf("Case %d: %d\n",id,ans);
43     }
44     return 0;
45     
46 }
View Code

 

posted @ 2020-11-12 11:02  过了样例  阅读(72)  评论(0)    收藏  举报