codechef - PALIN3
Posted arg-53
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codechef - PALIN3相关的知识,希望对你有一定的参考价值。
题目
https://www.codechef.com/problems/PALIN3
题解
求出每个位置的最长回文串,偶数长度的回文串找任意一侧三的倍数的段数,奇数长度的找使得 (2 * 段和 + 中心) mod 3 == 0 的段数,"0" 的单独考虑一下。
manacher 忘了更新最大左端点,卡了半天 :)
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)
typedef long long i64;
const int MAX = 1000010;
char S[MAX];
int pal[2 * MAX];
int _rem[MAX], _cnt[MAX][3];
int* rem = _rem + 1, (*cnt)[3] = _cnt + 1;
int main() {
scanf("%s", S);
int N = strlen(S);
int pfs = 0;
rep(i, N) {
int x = S[i] - ‘0‘;
pfs = (pfs + x) % 3;
rem[i] = pfs;
rep(j, 3) cnt[i][j] = cnt[i - 1][j];
cnt[i][pfs] += (S[i] != ‘0‘);
}
int l = -1, r = -1;
rep(z, 2 * N - 1) {
int i = (z + 1) >> 1;
int j = z >> 1;
int p = i >= r ? 0 : min(r - i, pal[2 * (l + r) - z]);
while (j + p + 1 < N && i - p - 1 >= 0 && S[j + p + 1] == S[i - p - 1]) ++p;
if (j + p > r) {
r = j + p;
l = i - p;
}
pal[z] = p;
}
i64 ans = 0;
for (int z = 0; z < 2 * N - 1; z += 2) {
if (pal[z] == 0) continue;
int c = z >> 1;
int t = (S[c] - ‘0‘) % 3;
if (t) t = 3 - t;
t = (t + rem[c - 1]) % 3;
ans += cnt[c + pal[z]][t] - cnt[c][t];
}
for (int z = 1; z < 2 * N - 1; z += 2) {
int c = z >> 1;
int t = rem[c];
ans += cnt[c + pal[z]][t] - cnt[c][t];
}
rep(i, N) ans += (S[i] % 3 == 0);
printf("%lld\\n", ans);
}
以上是关于codechef - PALIN3的主要内容,如果未能解决你的问题,请参考以下文章