题目:回文子串的最大长度
思想:字符串哈希+二分 OR Manacher
代码1:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2001000;//注意数组开的范围
typedef unsigned long long ULL;
char s[maxn];
ULL hr[maxn], hl[maxn], p[maxn];
int base = 131;
ULL query(ULL h[], int l, int r)
{
return h[r] - h[l-1]*p[r-l+1];
}
int main()
{
int ca = 0;
while(scanf("%s", s+1) && strcmp(s+1, "END"))
{
int n = strlen(s+1);
n *= 2;
for(int i = n; i > 0; i -= 2) //强行在数组中加入新的辅助符号
{
s[i] = s[i/2];
s[i-1] = 'z'+1;
}
p[0] = 1;
for(int i = 1, j = n; i <= n; i++, j--) //字符串哈希
{
hl[i] = hl[i-1]*base + (s[i]-'a'+1);
hr[i] = hr[i-1]*base +(s[j]-'a'+1);
p[i] = p[i-1]*base;
}
int res = 0;
int l, r;
for(int i = 1; i <= n; i++)
{
l = 0, r = min(i-1, n-i);
while(l < r)
{
int mid = (l+r+1)>>1;
if(query(hl, i-mid, i-1) != query(hr, n-(i+mid)+1, n-(i+1)+1))r = mid-1;
else l = mid;
}
if(s[i-l] <= 'z')res = max(res, l+1);
else res = max(res, l);
}
printf("Case %d: %d\n", ++ca, res);
}
return 0;
}
代码2:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2000100;
char Ma[maxn];
int Mp[maxn];
char s[maxn];
void Manacher(char s[], int len){
int l = 0;
Ma[l++] = '$';
Ma[l++] = '#';
for(int i = 0; i < len; i++){
Ma[l++] = s[i];
Ma[l++] = '#';
}
Ma[l] = 0;
int mx = 0, id = 0;
for(int i = 0; i < l; i++){
Mp[i] = mx > i ? min(Mp[2*id-i], mx-i):1;
while(Ma[i+Mp[i]] == Ma[i-Mp[i]])Mp[i]++;
if(i+Mp[i] > mx){
mx = i+Mp[i];
id = i;
}
}
}
int main(){
int ca = 0;
while(scanf("%s",s), strcmp(s, "END")){
int len = strlen(s);
Manacher(s, len);
int ans = 0;
for(int i = 0; i < 2*len+2; i++){
ans = max(ans, Mp[i]-1);
}
printf("Case %d: %d\n",++ca, ans);
}
return 0;
}