Solution - [CEOI2017]Palindromic Partitions

思路:

用两个指针 \(L\) 和 \(R\) ,分别指向字符串首尾。从两端同时枚举找到相同的字符串, \(s[1 - L]\) 和 \(s[R - n]\), 然后下次再从 \(L\) 和 \(R\) 出发,继续找到相同的字符串,如果最后找到字符串的长度不足 \(n\) 就将答案加 \(1\)。

例如:\(\texttt{bonobo}\)

先找到 \(s[1 - 2]=s[5-6]=\texttt{"bo"}\),已匹配字符串长度 \(:4\)

然后我们就会发现剩下的字符无法匹配,而且我们发现已匹配字符串长度不足 \(n\)。所以剩下的 \(\texttt{"no"}\) 只能单独为一部分。

故最后答案为 \(3\)

对于匹配字符串,我们可以用 \(hash\) 来维护,两个字符串 \(hash\) 值相等,则两个字符串可以匹配。

code

#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int maxn = 1e6 + 5; 
const int base = 31;
int Hash[maxn], Pow[maxn];
char s[maxn];
int gethash() {
	int len = strlen(s + 1);
	for (int i = 1; i <= len; i++) {
		Hash[i] = Hash[i - 1] * base + s[i];
	}
}
int get(int L, int R) {
	return Hash[R] - Hash[L - 1] * Pow[R - L + 1];
}
int ans;
signed main() {
	Pow[1] = base;
	for (int i = 2; i <= maxn; i++) Pow[i] = Pow[i - 1] * base;
	int t;
	ios::sync_with_stdio(false);
	cin >> t;
	while (t--) {
		cin >> s + 1;
		gethash();
		ans = 0;
		int len = strlen(s + 1), st = 0;
		int LL = 1, L = 1, RR = len, R = len;
		while (L < R) {
			if (get(LL, L) == get(R, RR)) {
				ans += 2;
				st += 2 * (L - LL + 1);
				L++;
				R--;
				LL = L;
				RR = R;
			} else {
				L++;
				R--;
			}
		}
		if (st < len) ans++;
		cout << ans << endl;
	}
	return 0;
}
上一篇:人类智慧贪心


下一篇:mtr命令详解诊断网络路由