POJ3974 Palindrome回文子串 (Hash + 二分)

题目链接

题意:

求最长回文串

思路:

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);
    }
}
发布了199 篇原创文章 · 获赞 156 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Harington/article/details/99643471
今日推荐