[hdu 6230 Palindrome] Manacher+树状数组

来源:互联网 发布:中国乐队 知乎 编辑:程序博客网 时间:2024/06/06 20:49

[hdu 6230 Palindrome] Manacher+树状数组

分类:Data Structure Manacher FenwickedTree

1. 题目链接

[hdu 6230 Palindrome]

2. 题意描述

给定一个字符串,统计有多少个子串是oneandhalf palindromic. (即字符串长度为3n2,且满足S[i]=S[2ni]=S[2n+i2](1in)
数据范围:字符串长度小于等于500000.

3. 解题思路

oneandhalf palindromic字符串稍作分析:可以发现,这种字符串的形式是这样的:$L(S)@R(S)$L(S)@
$@分别表示某一个小写字母。
L(S)R(S)分别表示某一个字符串,和该字符串的逆串(可为空串)。
首先,用Manacher预处理出每个字符为中心的最长回文串长度,p[i]
设子串中@,$ 在原串中的下标分别为i,j.
那么,该子串必然要满足:jp[j]+1i<ji+p[i]1.
然后,再用树状数组计数统计。

4. 实现代码

#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef long double lb;typedef unsigned int uint;typedef unsigned long long ull;typedef pair<int, int> pii;typedef pair<ll, ll> pll;typedef pair<ull, ull> puu;typedef pair<lb, lb> pbb;const int inf = 0x3f3f3f3f;const ll infl = 0x3f3f3f3f3f3f3f3fLL;template<typename T> inline void umax(T &a, T b) { a = max(a, b); }template<typename T> inline void umin(T &a, T b) { a = min(a, b); }template<typename T> inline T randIntv(const T& a, const T& b) { return (T)rand() % (b - a + 1) + a; }#ifdef ___LOCAL_WONZY___void debug() { cout << endl; }template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }#endifconst int MAXL = 500005;char s[MAXL * 2];int p[MAXL * 2], len1, len2;/*首先,i>=2 的 p 才有意义p[i]-1 为以 i 为中心的回文长度p[i]/2 表示回文半径i%2==0 表示这个位置为字符,i/2-1 表示原字符串的位置i%2==1 表示为字符中间,这两边的字符在原字符串的位置分别为 i/2-1 和 i/2*/int manacher(char *s) {    int len = strlen(s), id = 0, ans = 0;    for (int i = len; i >= 0; i--) {        s[i + i + 2] = s[i];        s[i + i + 1] = '#';    }    s[0] = '*';    for (int i = 2; i < 2 * len + 1; ++i) {        if (p[id] + id > i) p[i] = min(p[2 * id - i], p[id] + id - i);        else p[i] = 1;        while (s[i - p[i]] == s[i + p[i]]) p[i]++;        if (id + p[id] < i + p[i]) id = i;        ans = max(ans, p[i] - 1);    }    return ans;}ll c[MAXL * 2];void upd(int x, ll v) {    while (x <= len2) {        c[x] += v;        x += x & (-x);    }}ll qry(int x) {    ll ret = 0;    while (x > 0) {        ret += c[x];        x -= x & (-x);    }    return ret;}ll sum(int L, int R) { return qry(R) - qry(L - 1); }void clr(int x) { upd(x, -sum(x, x)); }int main() {#ifdef ___LOCAL_WONZY___    freopen ("input.txt", "r", stdin);#endif // ___LOCAL_WONZY___    int T; scanf("%d", &T);    while (T --) {        scanf("%s", s);        len1 = strlen(s); len2 = len1 * 2 + 1;        manacher(s);        vector<pii> line;        for (int i = 2; i < len2; i += 2) {            int r = p[i] / 2, s = i - (r - 1) * 2;            if (r <= 1) continue;            line.push_back(pii(s, i));        }        sort(line.begin(), line.end());        memset(c, 0, sizeof(c));        ll ans = 0, p = 0;        for (int i = 2; i < len2; i += 2) {            clr(i);            int r = ::p[i] / 2, j = i + (r - 1) * 2;            if (r <= 1) continue;            while (p < line.size() && line[p].first <= i) {                upd(line[p].second, 1);                ++ p;            }            ans += sum(i + 1, j);        }        printf("%lld\n", ans);    }#ifdef ___LOCAL_WONZY___    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // ___LOCAL_WONZY___    return 0;}
阅读全文
0 0
原创粉丝点击