Palindrome
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 603 Accepted Submission(s): 234
Problem Description
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.
Input
The first line is the number of test cases. For each test case, there is only one line containing a string(the length of strings is less than or equal to
500000), this string only consists of lowercase letters.
Output
For each test case, output a integer donating the number of one-and-half palindromic substrings.
Sample Input
1 ababcbabccbaabc
Sample Output
2
Hint
In the example input, there are two substrings which are one-and-half palindromic strings, $abab$ and $abcbabc$.
Source
2017CCPC哈尔滨站A题……
当时是全场AC率第三高的,然而英语水平有限,当时没有读懂题意,并没能AC,然而其实所谓的1.5回文串,就是一个回文串的回文中心被另一个回文串包含
可能是我比较蠢,所以只想出了一个办法,先Manacher求出所有的回文串并记录它们的右边界,放到set里统计,如果右边界无法包含当前的位置就删除,同时用BIT统计之前的所有回文串位置,当set中删除时BIT中一并删除。
居然跑了1700ms。。。慢的伤心。。。当时现场赛的时候,某个企业队好像用二分查找处理的字符串,生猛的一逼
#include <bits/stdc++.h>
#define lowbit(x) x & -x
#define LL long long
using namespace std;
const int MAXN = 500100;
const int INF = 0x7FFFFFFF;
template <typename T> inline void read(T &str) {
int ch = getchar(), cnt = 0;
while(ch > 'z' || ch < 'a') ch = getchar();
str[0] = (char) ch, ch = getchar();
while(ch <= 'z' && ch >= 'a') {
str[++cnt] = (char) ch;
ch = getchar();
}
return ;
}
struct node {
int i, rs;
node() {}
node(int _i = 0, int _rs = 0) : i(_i), rs(_rs) {}
bool operator < (const node & t) const {
return rs < t.rs || (rs == t.rs && i < t.i);
}
bool operator == (const node & t) const {
return (i == t.i) && (rs == t.rs);
}
};
char s1[MAXN << 1], s2[MAXN << 1];
int p[MAXN << 1], bit[MAXN], r[MAXN];
int n, T;
int len1, len2;
set<node>s;
void init() {
len1 = n;
s2[0] = '$';
s2[1] = '#';
for(int i = 0; i < len1; i++) {
s2[2 * i + 2] = s1[i];
s2[2 * i + 3] = '#';
}
len2 = len1 * 2 + 2;
s2[len2] = '&';
}
void manacher() {
int id = 0, mx = 0;
for(int i = 1; i < len2; i++) {
if(mx > i) p[i] = min(p[2 * id - i], mx - i);
else p[i] = 1;
while(s2[i + p[i]] == s2[i - p[i]]) p[i]++;
if(i + p[i] > mx) {
mx = i + p[i];
id = i;
}
}
}
inline void update(int x, int y) {
for(int i = x; i <= MAXN; i += lowbit(i)) bit[i] += y;
}
inline int query(int x) {
int ret = 0;
for(int i = x; i; i -= lowbit(i)) ret += bit[i];
return ret;
}
inline void Clear() {
memset(bit, 0, sizeof(bit));
s.clear();
}
inline void _push(node c) {
s.insert(c);
update(c.i, 1);
}
inline void _delete(node c) {
s.erase(c);
update(c.i, -1);
}
signed main() {
scanf("%d", &T);
while(T --) {
Clear();
read(s1);
n = (int) strlen(s1);
init();
manacher();
for(int i = 1; i <= n; i++) {
r[i] = (p[i * 2] - 1) >> 1;
}
LL ans = 0LL;
for(int i = 1; i <= n; i++) {
while(!s.empty() && s.begin()->rs < i) _delete(*s.begin());
ans += query(i) - query(i - r[i] - 1);
_push(node(i, i + r[i]));
}
printf("%lld\n", ans);
}
return 0;
}
如果谁有好的方法愿意告知,不胜感激