BZOJ4932遺伝子

遺伝子

長さが与えられた\(N- \)文字列\(S \)がある\(Q \)グループクエリ、与えられた各問い合わせ\(L、R&LT \) 要求し(S [l..r \ ] \)サブのパリンドロームな性質の異なる数を持っています。

オンライン余儀なくされました。\(N- \ ^のLeq 10. 5、Q≤2N \)

問題の解決策

ウェンWentao「回文ツリーとその応用。」

溶液

「ツリーパリンドロームの各点の右側に各キーのメンテナンス」メンテナンスを指す\((I、I \ SIM N)\) パリンドローム木。

、フロントに文字を追加します(フェイル\)\\(クイック\)バックエンドと同じです。

ポイントに変更を接合した後回文木の優れた自然は、その空にしないでください。

新しいノードのフロントエンドの文字に添加した場合の前上現れないかを決定するために必要とされ、これは最初の時間(INFとして表示されません)の各ブロックの各ノードのために維持することができます。

#include <bits/stdc++.h>
using namespace std;

const int N = 101010;
const int M = 350;

inline char get(void) {
    static char buf[100000], *S = buf, *T = buf;
    if (S == T) {
        T = (S = buf) + fread(buf, 1, 100000, stdin);
        if (S == T) return EOF;
    }
    return *S++;
}
template<typename T>
inline void read(T &x) {
    static char c; x = 0; int sgn = 0;
    for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
    if (sgn) x = -x;
}
inline void read(char *s) {
    static char c; int len = 0;
    for (c = get(); c < 'a' || c > 'z'; c = get());
    for (; c >= 'a' && c <= 'z'; c = get()) s[len++] = c;
    s[len] = 0;
}

char s[N];
int last_back, last_front, total;
int fail[N], len[N], ri[N];
int ch[N][30], quick[N][30];
int block_front[M][N], ans[M][N], block_time[M][N];
int visit[N];
int type, lastans, clocks;
int n, q, l, r, B;
int belong[N];

inline void ExtendFront(int pos, int r) {
    int p = last_front, key = s[pos];
    if (s[pos + len[p] + 1] != key || pos + len[p] + 1 > r) p = quick[p][key];
    if (!ch[p][key]) {
        int np = ++total, q = fail[p];
        len[np] = len[p] + 2;
        if (s[pos + len[q] + 1] == key) fail[np] = ch[q][key];
        else fail[np] = ch[quick[q][key]][key];
        memcpy(quick[np], quick[fail[np]], sizeof quick[np]);
        quick[np][s[pos + len[fail[np]]]] = fail[np];
        ch[p][key] = np;
    }
    last_front = ch[p][key];
    if (len[last_front] == r - pos + 1) last_back = last_front;
}
inline void ExtendBack(int l, int pos) {
    int p = last_back, key = s[pos];
    if (s[pos - len[p] - 1] != key || pos - len[p] - 1 < l) p = quick[p][key];
    if (!ch[p][key]) {
        int np = ++total, q = fail[p];
        len[np] = len[p] + 2;
        if (s[pos - len[q] - 1] == key) fail[np] = ch[q][key];
        else fail[np] = ch[quick[q][key]][key];
        memcpy(quick[np], quick[fail[np]], sizeof quick[np]);
        quick[np][s[pos - len[fail[np]]]] = fail[np];
        ch[p][key] = np;
    }
    last_back = ch[p][key];
    if (len[last_back] == pos - l + 1) last_front = last_back;
}

int main(void) {
    read(type); read(n); read(q);
    read(s + 1); s[0] = -1;
    for (int i = 1; i <= n; i++) s[i] -= 'a';
    B = sqrt(n);
    for (int i = 1; i <= n; i++) belong[i] = (i - 1) / B + 1;

    memset(block_time, 0x3f, sizeof block_time);
    fail[0] = fail[1] = 1; len[1] = -1; total = 1;
    for (int i = 0; i < 26; i++) quick[0][i] = quick[1][i] = 1;

    for (int i = 0; i < belong[n]; i++) {
        ++clocks; last_back = last_front = 0;
        int st = i * B + 1;
        for (int j = st; j <= n; j++) {
            ExtendBack(st, j);
            block_front[i][j] = last_front; ans[i][j] = ans[i][j - 1];
            if (visit[last_back] != clocks) {
                ++ans[i][j]; visit[last_back] = clocks;
                block_time[i][last_back] = j;
            }
        }
    }

    while (q--) {
        read(l); read(r); ++clocks;
        l ^= type * lastans;
        r ^= type * lastans;
        if (l > r) swap(l, r);
        if (belong[l] == belong[r]) {
            last_back = last_front = 0; lastans = 0;
            for (int i = r; i >= l; i--) {
                ExtendFront(i, r);
                if (visit[last_front] != clocks) {
                    ++lastans; visit[last_front] = clocks;
                }
            }
        } else {
            lastans = ans[belong[l]][r];
            last_front = block_front[belong[l]][r];
            for (int i = belong[l] * B; i >= l; i--) {
                ExtendFront(i, r);
                if (visit[last_front] != clocks) {
                    visit[last_front] = clocks;
                    if (block_time[belong[l]][last_front] > r) ++lastans;
                }
            }
        }
        printf("%d\n", lastans);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/autoint/p/11966573.html