题意
传送门 P3501 [POI2010]ANT-Antisymmetry
题解
将字符串 S S S 各位反转得到 r S rS rS,可以观察到满足条件的子串满足类似回文串的性质。假设长为 x x x 的子串对称中心左边第一个字符为 i i i,则有 S [ i − x + 1 , i ] = r S [ i + 1 , i + x ] S[i-x+1,i]=rS[i+1,i+x] S[i−x+1,i]=rS[i+1,i+x]。 H a s h Hash Hash 预处理 S , r S S,rS S,rS,枚举对称中心,二分满足条件的子串的最长长度,同时更新答案。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 500005, bs = 131;
char S[maxn], rS[maxn];
int N;
ull B[maxn], F[maxn], rF[maxn];
inline bool judge(int i, int x) {
return F[i] - F[i - x] * B[x] == rF[i + 1] - rF[i + x + 1] * B[x]; }
int main()
{
scanf("%d", &N);
scanf("%s", S + 1);
for (int i = 1; i <= N; ++i)
rS[i] = S[i] == '0' ? '1' : '0';
B[0] = 1;
for (int i = 1; i <= N; ++i)
B[i] = B[i - 1] * bs, F[i] = F[i - 1] * bs + S[i] - '0' + 1;
for (int i = N; i; --i)
rF[i] = rF[i + 1] * bs + rS[i] - '0' + 1;
ll res = 0;
for (int i = 1; i <= N; ++i)
{
int lb = 0, ub = min(i, N - i) + 1;
while (ub - lb > 1)
{
int mid = (lb + ub) >> 1;
if (judge(i, mid))
lb = mid;
else
ub = mid;
}
res += lb;
}
printf("%lld\n", res);
return 0;
}