[NOI2018] Your name problem solution

Title link
consider practice 68 points:
seeking occurs in the A string, and the number of strings in the string B did not occur.
Using inclusion and exclusion, with a different number of sub-strings A, minus the number of different common string A, B's.
First with double pointer, determine the start of each position A, up to match how far back in B.
The question then becomes, to give you some range, ask how many different strings have their sub-interval.
Because each string, are the original interval \ ([l, r] \ ) in \ ([l, i] \ ) suffix. \ ((l <= i <
= r) \) and in front of the extension is to remove some characters, it is the continuous walking fa.
It is possible to build a tree edge fa, and then locate the position of these, find the point to the root and the path of these.
Use Tree chain to merge, to pay attention to compression problems.
100 practices: 68 and substantially the same, is determined substring \ ([a, b] \ ) whether there is more than a limit ( \ (L <= A, B <= R & lt \) ).
A string matching the position, the tree is a collection of the idea of the red dot.
Prefix corresponding to the red dot, so this limitation is to be converted prefixed limit position.
Is there a number of x ~ y a point determination requires subtrees. Chairman of the sequence using DFS + tree can be.

Code:

#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;
}

Guess you like

Origin www.cnblogs.com/lnzwz/p/11354710.html