思路:
用两个指针 \(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;
}