@loj - 2720 @ "NOI2018" your name


@description@

ION year set a string name, the name of the requirements of each question must be a non-empty substring year in a row named strings, and can not name any one topic is the same as the previous year.
Because some special reasons, has been named A small string of ION2017.
A small Q times have now asked: each given ION2017 ION2018 name strings and string name, there are several requirements subject name, the name is such that a continuous non-null sub ION2018 named string and string and will not the same as any one topic ION2017 name.
Because some special reasons, all names given ION2017 inquiries are continuous string of sub-string of a string.

Input format
name.in reads data from the file.
The first line of a string S, named after the inquiry are given ION2017 continuous string of substrings S.
The second line a positive integer Q, represents the number of interrogation.
Next Q lines, each line having a string of two positive integers and T l, r, represents the query string name is ION2017 If S [l, r], ION2018 name string is T, then, there are several ways certain naming meet the requirements.
Ensure that the input string is given by the lowercase configuration.

Output format
output to a file name.out in.
Q output line, the i-th row represents a non-negative integer i th answer inquiries.

Sample input. 1
scbamgepe
. 3
smape 2. 7
sbape. 3. 8
sgepe. 9. 1
Sample Output 1
12 is
10
. 4

Data range and tips
for all data, guaranteed. 1 <= L <= R & lt <= | S | <=. 5 10 ^. 5,. 1 <= | T | <=. 5 10 ^. 5, [Sigma | T | <= 10 ^. 6 , Q <= 10 ^ 5.

@solution@

Consider l = 1, r = | S | case.

We wish to build an S suffix automaton, then ran to get a run on T S. For each prefix of T i, we obtain a maximum f [i], such that the prefix length T i is f [i] is the suffix of S sub-string.
Obviously the length of the prefix i <= all suffixes f [i] also appeared in S.

We then build the T suffix automaton, then the marked f [i] of each tag corresponds to a prefix node, and then pass along a parent tag tree.
This way can process T suffix automaton string corresponding to each node number does not appear in S. So we can solve the problem of inquiry.

Then consider a given string is a substring S [l ... r] S when we consider as determined for each i f [i].
We can consider the use of combined persistent segment tree, each node obtains the suffix automaton set S of end-pos.

When T i of the prefix node matches the suffix automaton S x, if the matching is successful as possible in S [l ... r], we must be set to select end-pos <= r as large as possible, and that. Binary tree line click.
If there is such an end-pos or the end-pos corresponding string beyond the left point, we as the match fails, continue to jump along the parent tree.

So down, for it takes a tree line, so the time complexity is O (| T | * logn) is.

@accepted code@

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1000000;
struct segtree{
    struct node{
        int ch[2], mx;
    }pl[20*MAXN + 5];
    int ncnt;
    segtree() {ncnt = 0; pl[0].mx = -1;}
    void pushup(int x) {
        if( pl[x].ch[1] ) pl[x].mx = pl[pl[x].ch[1]].mx;
        else pl[x].mx = pl[pl[x].ch[0]].mx;
    }
    int merge(int a, int b) {
        if( !a ) return b;
        if( !b ) return a;
        int c = (++ncnt);
        pl[c].ch[0] = merge(pl[a].ch[0], pl[b].ch[0]);
        pl[c].ch[1] = merge(pl[a].ch[1], pl[b].ch[1]);
        pushup(c);
        return c;
    }
    int insert(int a, int l, int r, int p) {
        int b = (++ncnt); pl[b].ch[0] = pl[a].ch[0], pl[b].ch[1] = pl[a].ch[1];
        if( l == r ) {
            pl[b].mx = l;
            return b;
        }
        int mid = (l + r) >> 1;
        if( p <= mid ) pl[b].ch[0] = insert(pl[a].ch[0], l, mid, p);
        else pl[b].ch[1] = insert(pl[a].ch[1], mid + 1, r, p);
        pushup(b);
        return b;
    }
    int query(int x, int l, int r, int p) {
        if( l == r ) return pl[x].mx;
        int mid = (l + r) >> 1;
        if( p <= mid ) return query(pl[x].ch[0], l, mid, p);
        else {
            int k = query(pl[x].ch[1], mid + 1, r, p);
            if( k != -1 ) return k;
            else return pl[pl[x].ch[0]].mx;
        }
    }
};
struct SAM{
    struct node{
        node *ch[26], *fa;
        int mx, pos, tag;
    }pl[2*MAXN + 5], *lst, *root, *ncnt;
    SAM() {ncnt = lst = root = &pl[0];}
    void clear() {
        int size = ncnt - pl + 1;
        for(int i=0;i<size;i++) {
            for(int j=0;j<26;j++)
                pl[i].ch[j] = NULL;
            pl[i].fa = NULL, pl[i].mx = pl[i].pos = pl[i].tag = 0;
        }
        ncnt = lst = root = &pl[0];
    }
    void extend(int c) {
        node *cur = (++ncnt), *p = lst; lst = cur;
        cur->mx = cur->pos = p->mx + 1;
        while( p && p->ch[c] == NULL )
            p->ch[c] = cur, p = p->fa;
        if( !p )
            cur->fa = root;
        else {
            node *q = p->ch[c];
            if( p->mx + 1 == q->mx )
                cur->fa = q;
            else {
                node *cne = (++ncnt); (*cne) = (*q);
                cne->mx = p->mx + 1; cne->pos = 0;
                cur->fa = q->fa = cne;
                while( p && p->ch[c] == q )
                    p->ch[c] = cne, p = p->fa;
            }
        }
    }
    node *a[2*MAXN + 5]; int b[2*MAXN + 5];
    segtree T; int rt[2*MAXN + 5];
    void sort(int len) {
        int size = ncnt - pl + 1;
        for(int i=1;i<=len;i++) b[i] = 0;
        for(int i=0;i<size;i++) b[pl[i].mx]++;
        for(int i=1;i<=len;i++) b[i] += b[i-1];
        for(int i=0;i<size;i++) a[--b[pl[i].mx]] = &pl[i];
    }
    void build(int len) {
        int size = ncnt - pl + 1; sort(len);
        for(int i=0;i<size;i++)
            rt[i] = 0;
        for(int i=size-1;i>0;i--) {
            if( a[i]->pos )
                rt[a[i]-pl] = T.insert(rt[a[i]-pl], 1, len, a[i]->pos);
            rt[a[i]->fa-pl] = T.merge(rt[a[i]->fa-pl], rt[a[i]-pl]);
        }
    }
    long long solve(int len) {
        int size = ncnt - pl + 1; sort(len);
        long long ret = 0;
        for(int i=size-1;i>0;i--)
            a[i]->fa->tag = min(a[i]->fa->mx, max(a[i]->fa->tag, a[i]->tag)), ret += max(0, a[i]->mx - max(a[i]->fa->mx, a[i]->tag));
        return ret;
    }
    void debug(int len) {
        int size = ncnt - pl + 1;
        for(int i=0;i<size;i++) {
            printf("%d : %d %d %d %d\n", i, pl[i].fa-pl, pl[i].mx, pl[i].pos, pl[i].tag);
            //T.debug(rt[i], 1, len);
        }
        puts("");
    }
}S, T;
char str[MAXN + 5];
int mx[MAXN + 5];
int main() {
    freopen("name.in", "r", stdin);
    freopen("name.out", "w", stdout);
    scanf("%s", str);
    int lenS = strlen(str);
    for(int i=0;i<lenS;i++)
        S.extend(str[i] - 'a');
    S.build(lenS);
    int Q; scanf("%d", &Q);
    for(int i=1;i<=Q;i++) {
        int l, r, lenT;
        scanf("%s%d%d", str, &l, &r), lenT = strlen(str);
        SAM::node *nw = S.root; int tmp = 0, x;
        for(int j=0;j<lenT;j++) {
            while( nw && nw->ch[str[j]-'a'] == NULL )
                nw = nw->fa;
            if( nw ) {
                tmp = min(tmp, nw->mx) + 1, nw = nw->ch[str[j]-'a'];
                x = S.T.query(S.rt[nw-S.pl], 1, lenS, r);
                while( nw ) {
                    if( x == -1 ) nw = nw->fa;
                    else {
                        if( nw == S.root || l + nw->fa->mx <= x ) break;
                        else nw = nw->fa;
                    }
                    if( nw ) x = S.T.query(S.rt[nw-S.pl], 1, lenS, r);
                }
                if( nw )
                    tmp = min(tmp, min(x - l + 1, nw->mx));
                else tmp = 0, nw = S.root;
            }
            else tmp = 0, nw = S.root;
            mx[j] = tmp;
        }
        for(int j=0;j<lenT;j++)
            T.extend(str[j]-'a');
        nw = T.root;
        for(int j=0;j<lenT;j++) {
            nw = nw->ch[str[j]-'a'];
            nw->tag = mx[j];
        }
        printf("%lld\n", T.solve(lenT));
        T.clear();
    }
}

@details@

Because we want to build multiple T suffix automaton, so every time after asking to pay attention to empty the T suffix automata.

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11361871.html