求调:哈希二分求最长回文串
  • 板块学术版
  • 楼主_RainCappuccino_
  • 当前回复5
  • 已保存回复5
  • 发布时间2023/12/26 16:26
  • 上次更新2023/12/26 20:01:56
查看原帖
求调:哈希二分求最长回文串
857626
_RainCappuccino_楼主2023/12/26 16:26

网上流行的做法是在两两字符之间加上一个 # 然后全部当做奇数长度的回文串来求。

但是我是对于每个回文点 ii 分别二分奇数长度最多为多少,和偶数长度最多为多少,然后分别取 max,但是却出现了答案为偶数但是我输出比其小1的情况。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N = 1e6 + 10;
const ull pri = 131;
ull h[N], h2[N], p[N] = {1};
ull subhs (int l, int r) {
	return h[r] - h[l - 1] * p[r - l + 1];
}
ull subhs2(ull l, ull r) {
	return h2[l] - h2[r + 1] * p[r - l + 1];
}
string s;
void init() {
	for (int i = 1; i <= (int)s.size(); i ++) h[i] = h[i - 1] * pri + s[i - 1];
	for (int i = (int)s.size() ; i >= 1; i --) h2[i] = h2[i + 1] * pri + s[i - 1];
}
signed main() {
	ios::sync_with_stdio(0);
	for (int i = 1; i <= 1e6; i ++) p[i] = p[i - 1] * pri;
	int cas = 0;
	while(cin >> s) {
		if(s == "END") return 0;
		init();
		int n = s.size(), ans = 0;
		for (int i = 1; i <= n; i ++) {
			// 对于奇数长度的回文串
			int l = 1, r = min(i - 1, n - i);
			while(l < r) {
				int mid = (l + r + 1) >> 1;
				if(subhs(i - mid, i - 1) == subhs2(i + 1, i + mid)) l = mid;
				else r = mid - 1;
			}
			if(subhs(i - l, i - 1) == subhs2(i + 1, i + l)) ans = max(ans, l * 2 + 1);
			// 对于偶数长度的回文串
			if(i == n) continue;
			l = 1, r = min(i, n - i);
			while(l < r) {
				int mid = (l + r + 1) >> 1;
				if(subhs(i - mid + 1, i) == subhs2(i + 1, i + mid)) l = mid;
				else r = mid - 1;
			}
			if(subhs(i - l + 1, i) == subhs2(i + 1, i + l)) ans = max(ans, l * 2);
		}
		cout << "Case " << ++ cas << ": " << ans << endl;
	}
}
2023/12/26 16:26
加载中...