Alice like strings, especially long strings. For each string, she has a special evaluation system to judge how elegant the string is. She defines that a string S[1..3n−2](n≥2) is one-and-half palindromic if and only if it satisfies S[i]=S[2n−i]=S[2n+i−2](1≤i≤n).For example, abcbabc is one-and-half palindromic string, and abccbaabc is not. Now, Alice has generated some long strings. She ask for your help to find how many substrings which is one-and-half palindromic.
题目意思就是 问有多少个满足要求的1.5回文串, 这个回文串如果只关注,对称中心的话,那么就是 问你有多少对,两个相互交叠的回文中心,交叠就是 两者的对称中心+半径覆盖到了对方。
解:本来想用主席树的,但是大家都用的树状数组,那就学一下。
每次ans+上的是 从前面找到后面。 我们要把每个点恰好到达的那个点释放了,这样不会影响答案。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e6 + 10;
typedef long long ll;
int T;
char t[maxn], s[maxn];
int n, p[maxn];
void init() {
int len = strlen(t);
s[0] = '$'; s[1] = '#';
n = 2;
for (int i = 0; i < len; i++) {
s[n++] = t[i]; s[n++] = '#';
}
s[n] = 0;
}
void manacher() {
int id, mx = 0;
for (int i = 1; i < n; i++) {
if (i < mx) p[i] = min(p[2*id-i], mx-i);
else p[i] = 1;
while (s[i-p[i]] == s[i+p[i]]) p[i]++;
if (mx < i + p[i]) { id = i; mx = i + p[i]; }
}
int m = n;
n = 0;
for (int i = 1; i < m; i++) if (s[i] != '#') p[++n] = p[i]/2 ;
}
ll C[maxn];
int lowbit(int x) { return x & (-x); }
ll sum(int x) {
ll ans = 0;
while (x > 0) { ans += C[x]; x -= lowbit(x); }
return ans;
}
void add(int x, int d) {
while (x <= n) { C[x] += d; x += lowbit(x); }
}
vector<int> v[maxn];
int main() {
#ifdef swt
freopen("input2.txt","r",stdin);
#endif // swt
#define en '\n'
scanf("%d", &T);
while (T--) {
scanf("%s", t);
init();
manacher();
for (int i = 1; i <= n; i++) v[i].clear();
for (int i = 1; i <= n; i++) v[i-p[i]+1].push_back(i);
for (int i = 1; i <= n; i++) C[i] = 0;
ll ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < v[i].size(); j++) add(v[i][j] ,1);
ans += (sum(i + p[i]-1) - sum(i));
}
printf("%lld\n", ans);
}
return 0;
}
同理:我从后往前更新也是对的
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e6 + 10;
typedef long long ll;
int T;
char t[maxn], s[maxn];
int n, p[maxn];
void init() {
int len = strlen(t);
s[0] = '$'; s[1] = '#';
n = 2;
for (int i = 0; i < len; i++) {
s[n++] = t[i]; s[n++] = '#';
}
s[n] = 0;
}
void manacher() {
int id, mx = 0;
for (int i = 1; i < n; i++) {
if (i < mx) p[i] = min(p[2*id-i], mx-i);
else p[i] = 1;
while (s[i-p[i]] == s[i+p[i]]) p[i]++;
if (mx < i + p[i]) { id = i; mx = i + p[i]; }
}
int m = n;
n = 0;
for (int i = 1; i < m; i++) if (s[i] != '#') p[++n] = p[i]/2 ;
}
ll C[maxn];
int lowbit(int x) { return x & (-x); }
ll sum(int x) {
ll ans = 0;
while (x > 0) { ans += C[x]; x -= lowbit(x); }
return ans;
}
void add(int x, int d) {
while (x <= n) { C[x] += d; x += lowbit(x); }
}
vector<int> v[maxn];
int main() {
#ifdef swt
freopen("input2.txt","r",stdin);
#endif // swt
#define en '\n'
scanf("%d", &T);
while (T--) {
scanf("%s", t);
init();
manacher();
for (int i = 1; i <= n; i++) v[i].clear();
for (int i = 1; i <= n; i++) v[i+p[i]-1].push_back(i);
for (int i = 1; i <= n; i++) C[i] = 0;
ll ans=0;
for (int i = n; i>=1; --i) {
for (int j = 0; j < v[i].size(); j++) add(v[i][j],1);
ans += sum(i-1) - sum(i-p[i]);
}
printf("%lld\n", ans);
}
return 0;
}