题目链接
题意:
求最长回文串
思路:
Manacher 解法
Hash 解法 :
1)Hash 和回文串之间的联系: 一个字符串如果是 回文字符串那么这个字符串的正反Hash值相同
2)正向求一遍Hash 反向求一遍 Hash,二分查找回文串长度(奇数长度或者偶数长度)。
Hash学习路径
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
const int MAXN=1e6+5;
const int p = 31;
typedef unsigned long long ll;
ll Hash1[MAXN], Hash2[MAXN], p_x[MAXN];
char s[MAXN];
int len, Ans;
void initHash() {
for (int i = 0; i < len; ++i) {
s[i] = s[i] - 'a' + 1;
}
Hash1[0] = s[0];
for(int i = 1; i < len; ++i) {
Hash1[i] = Hash1[i - 1] * p + s[i];
}
Hash2[len - 1] = s[len - 1];
for(int i = len - 2; i >= 0; --i) {
Hash2[i] = Hash2[i + 1] * p + s[i];
}
}
ll askHash1(int l, int r) {
if(l == 0)
return Hash1[r];
else
return Hash1[r] - Hash1[l - 1] * p_x[r - l + 1];
}
ll askHash2(int l, int r) {
if(r == len - 1)
return Hash2[l];
else
return Hash2[l] - Hash2[r + 1] * p_x[r - l + 1];
}
bool check (int n){
ll hash1, hash2;
int left, right;
for(int i = 0; i + n - 1 < len; ++i) {
left = i;
right = i + n - 1;
hash1 = askHash1(left, right);
hash2 = askHash2(left, right);
if(hash1 == hash2)
return true;
}
return false;
}
void binarySearch(int left, int right, vector<int> vt) {
int mid;
while(left <= right){
mid = (left + right) >> 1;
if(check(vt[mid])) {
Ans = max (Ans, vt[mid]);
left = mid + 1;
} else
right = mid - 1;
}
}
int main()
{
p_x[0]=1;
for(int i = 1; i < MAXN; i++)
p_x[i] = p_x[i-1] * p;
int Case = 0;
while(scanf("%s", &s)) {
Ans = 0;
if(strcmp(s,"END") == 0)
break;
len = strlen(s);
initHash();
vector<int> odd, even;
for(int i = 1; i <= len; ++i){
if(i % 2)
odd.push_back(i);
else
even.push_back(i);
}
binarySearch(0, odd.size() - 1, odd);
binarySearch(0, even.size() - 1, even);
printf("Case %d: %d\n", ++Case, Ans);
}
}