[NOI2018]あなたの名前の問題解決

タイトルリンク
練習68点を考慮してください。
シークは、文字列で発生し、文字列B内の文字列の数は発生しませんでした。
サブストリングAの異なる数、マイナス異なる共通の文字列A、Bの数と、包含および除外を使用して。
どこまで戻っB.で一致するまで最初の二重ポインタで、それぞれの位置Aの開始を決定
問題はその後、あなたにいくつかの範囲を与える彼らのサブ間隔を持っているどのように多くの異なる文字列依頼する、となります。
各ストリングので、元の間隔である\([L、R] \ ) で\([L、I] \ ) サフィックス。\((L <= I <
= R)\) と拡張の前に、それが連続歩行FAであり、いくつかの文字を除去することです。
ツリーエッジFAを構築し、その後、これらの位置を見つけ、ルートをポイントし、これらのパスを見つけることが可能です。
圧縮の問題に注意を払うように、マージするツリー・チェーンを使用してください。
100回のプラクティス:68と実質的に同一の、決定されたサブストリングである([B] \ \ ) 限界(以上存在するか否かを\(L <= A、B <= R&LTの\)で)。
位置に一致する文字列が、木は赤い点のアイデアを集めたものです。
プレフィックスは赤い点に対応するので、この制限は、プレフィックス限界位置に変換されます。
ポイント決意がサブツリーを必要と〜yのxの数があります。することができDFS +ツリーを使用してシーケンスの会長。

コード:

#include <stdio.h> 
#include <stdlib.h> 
#define ll long long 
int fr[2000010],ne[2000010];
int v[2000010],bs = 0;
int wl[2000010],wr[2000010],tm = 1;
int xl[2000010];
struct SAM {
    int trs[2000010][26],fa[2000010];
    int len[2000010],np,sl;
    int red[2000010];
    SAM() {
        np = sl = 1;
    }
    void clean() {
        for (int i = 1; i <= sl; i++) {
            fa[i] = len[i] = 0;
            red[i] = false;
            for (int j = 0; j < 26; j++) trs[i][j] = 0;
        }
        np = sl = 1;
    }
    void insert(char c, int wz) {
        c -= 'a';
        int p = np;
        np = ++sl;
        len[np] = len[p] + 1;
        while (p != 0 && trs[p][c] == 0) {
            trs[p][c] = np;
            p = fa[p];
        }
        if (p == 0) fa[np] = 1;
        else {
            int q = trs[p][c];
            if (len[q] == len[p] + 1) fa[np] = q;
            else {
                int nq = ++sl;
                fa[nq] = fa[q];
                fa[q] = fa[np] = nq;
                len[nq] = len[p] + 1;
                for (int j = 0; j < 26; j++) trs[nq][j] = trs[q][j];
                while (p != 0 && trs[p][c] == q) {
                    trs[p][c] = nq;
                    p = fa[p];
                }
            }
        }
        red[np] = wz;
    }
};
void addb(int a, int b) {
    v[bs] = b;
    ne[bs] = fr[a];
    fr[a] = bs;
    bs += 1;
}
SAM S,T;
void dfs1(int u) {
    xl[tm] = u;
    wl[u] = tm++;
    for (int i = fr[u]; i != -1; i = ne[i]) dfs1(v[i]);
    wr[u] = tm;
}
int up[1000010];
char zf[1000010];
struct SPx {
    int u,cd;
    SPx() {}
    SPx(int U, int Cd) {
        u = U;
        cd = Cd;
    }
};
SPx px[1000010];
ll baoli(int s) {
    for (int i = 1; i <= T.sl; i++) up[i] = 0;
    for (int i = 0; i < s; i++) {
        int cd = px[i].cd,
        u = px[i].u;
        while (u != 1) {
            if (up[u] == T.len[u] - T.len[T.fa[u]]) break;
            if (cd - T.len[T.fa[u]] > up[u]) up[u] = cd - T.len[T.fa[u]];
            u = T.fa[u];
            cd = T.len[u];
        }
    }
    ll rtn = 0;
    for (int i = 2; i <= T.sl; i++) rtn += up[i];
    return rtn;
}
int he[24000010],cl[24000010],cr[24000010],sl = 0;
int jianshu(int l, int r) {
    int rt = sl++;
    he[rt] = 0;
    if (l + 1 == r) return rt;
    int m = (l + r) >> 1;
    cl[rt] = jianshu(l, m);
    cr[rt] = jianshu(m, r);
    return rt;
}
int xiugai(int i, int l, int r, int j, int x) {
    int rt = sl++;
    if (l + 1 == r) {
        he[rt] = he[i] + x;
        return rt;
    }
    cl[rt] = cl[i];
    cr[rt] = cr[i];
    int m = (l + r) >> 1;
    if (j < m) cl[rt] = xiugai(cl[rt], l, m, j, x);
    else cr[rt] = xiugai(cr[rt], m, r, j, x);
    he[rt] = he[cl[rt]] + he[cr[rt]];
    return rt;
}
int chaxun(int i, int l, int r, int L, int R) {
    if (R <= l || r <= L) return 0;
    if (L <= l && r <= R) return he[i];
    int m = (l + r) >> 1;
    return chaxun(cl[i], l, m, L, R) + chaxun(cr[i], m, r, L, R);
}
int gen[1000010],n;
bool zichuan(int i, int l, int r, int cd) {
    l = l + cd - 1;
    if (l > r) return false;
    int z = chaxun(gen[wr[i] - 1], 1, n + 1, l, r + 1) - chaxun(gen[wl[i] - 1], 1, n + 1, l, r + 1);
    return z > 0;
}
int main() {
    scanf("%s", zf);
    for (n = 0; zf[n] != 0; n++) S.insert(zf[n], n + 1);
    for (int i = 1; i <= S.sl; i++) fr[i] = -1;
    for (int i = 1; i <= S.sl; i++) addb(S.fa[i], i);
    dfs1(1);
    gen[0] = jianshu(1, n + 1);
    for (int i = 1; i < tm; i++) {
        if (S.red[xl[i]] != 0) gen[i] = xiugai(gen[i - 1], 1, n + 1, S.red[xl[i]], 1);
        else gen[i] = gen[i - 1];
    }
    int m;
    scanf("%d", &m);
    for (int i = 0; i < m; i++) {
        int l,r,x = 1,y = 1,s = 0;
        scanf("%s%d%d", zf, &l, &r);
        T.clean();
        for (int j = 0; zf[j] != 0; j++) T.insert(zf[j], 0);
        for (int j = 0, k = -1, c = 0; zf[j] != 0; j++) {
            c -= 1;
            if (x != 1 && k - j == S.len[S.fa[x]]) x = S.fa[x];
            if (y != 1 && k - j == T.len[T.fa[y]]) y = T.fa[y];
            if (k < j) k = j,
            c = 0;
            while (zf[k] != 0 && S.trs[x][zf[k] - 'a'] != 0 && zichuan(S.trs[x][zf[k] - 'a'], l, r, c + 1)) {
                c += 1;
                x = S.trs[x][zf[k] - 'a'];
                y = T.trs[y][zf[k] - 'a'];
                px[s++] = SPx(y, c);
                k += 1;
            }
        }
        ll zo = 0;
        for (int j = 1; j <= T.sl; j++) zo = zo + T.len[j] - T.len[T.fa[j]];
        printf("%lld\n", zo - baoli(s));
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/lnzwz/p/11354710.html