@loj - 3049 @ "twelve provinces exam 2019" string problem


@description@

A conventional string S.
Na Tiffany from the divided substrings as class A string, the i-th Ai = S [la [i] ... ra [i]].
Nb Yazid divided out from as a B-type sequence substring, the i-th Bi = S [lb [i] ... rb [i]].
M group dominance is given (x, y), x represents the Class A Class B disposable strings of string y.
Use of any Type A plurality of strings spliced together to get the longest string of the target T, to meet the two adjacent strings of class A, class B sequence before a certain class A prefix string is disposable after a string of A class.
If infinite, the output of -1.

Input format
from the standard input data.
The first row contains a single test a plurality of sets of data points, the input comprises a non-negative integer and T represents the number of data sets. Next, each set of data described in turn, for each set of data:

Line 1 contains only a lowercase string S.
Line a non-negative integer 2 na, A represents the number of class strings. Next na row, two space-separated integers per line.
This part of the two numbers in the i th row, respectively la [i], ra [i ], the i-th class A description string.
To ensure that 1 <= la [i] < = ra [i] <= | S |.
The next line a non-negative integer nb, B represents the number of classes strings. Next nb rows, two space-separated integers each row.
This part of the two numbers in row i were lb [i], rb [i ], i-described Class B string.
To ensure that 1 <= lb [i] < = rb [i] <= | S |.
The next line a non-negative integer m, represents a group dominant relationship. Next m lines, each line separated by a space of two integers.
In this part two integers each line x, y, describing one pair (x, y) of the relations of domination, see the specific meaning of "subject description."
To ensure that 1 <= x <= na, 1 <= y <= nb. Ensure that all pairwise disjoint relations of domination that governed the relationship between the two groups x does not exist, y are the same.

Output format
to standard output.
Sequentially outputs each data answer, for each set of data:
line a string length representing the maximum integer. Particularly, if the string satisfies the restriction may be infinitely long, please outputs -1.

Sample input. 1
. 3
abaaaba
2
. 4. 7
. 1. 3
. 1
. 3. 4
. 1
2. 1
abaaaba
2
. 4. 7
. 1. 3
. 1
. 7. 7
. 1
2. 1
abbaabbaab
. 4
. 1. 5
. 4. 7
. 6. 9
. 8 10
. 3
. 1. 6
10 10
. 4. 6
. 5
. 1 2
. 1 . 3
2 1
. 3. 3
. 4 1
sample output 1
. 7
-1
13 is
Example Description 1
for the first group of data, A and class series having aaba aba, category B series having aa, and A2 dominated B1. We can find the string abaaaba, it can be split into A2 + A1, A1 and A2 comprise a prefixed dominated B1. It may prove more satisfying the constraint length of the string does not exist.
For the second data set, the first set of data with the only difference is that only class B sequence is a. Easy to prove the existence of infinitely long string meet the limits.
For the third data set, it is easy to prove abbaabbaaaabb longest string satisfying the constraint.

Tips range data
for each set of data in all the test points, to ensure that: 1 <= | S | < = 2 * 10 ^ 5, na, nb <= 2 * 10 ^ 5, m <= 2 * 10 ^ 5 .
And | S |, na, the total sum nb, m, respectively, does not exceed the limit of the test point corresponding single set of data 10 times.

@solution@

Ai behind each contact can be set is a class A fixed string, so we can Ai behind it can be connected to the A class side of series.
Running a simple topological sort, if there is no solution the ring, or may be the side edge of selecting the maximum value dp sort DAG.

Now consider the optimization of the construction side of it.
We may each be a Class A Class B series string to the side at its disposal, each type of a string of series B side to the A class to class B prefix string.
Even the first half side is O (m), and we continue to consider optimizing later.

If Bj = S [lb [j] ... rb [j]] is Ai = S [la [i] ... ra [i]] prefix, then this condition is in fact the | Ai |> = | Bj | and lcp (lb [j], la [i])> = | Bj | equivalent.
May be learned by the suffix array, a suffix and lb [j] of the lcp> = suffix actually form a certain value range.
So consider using persistence can help us even edge segment tree.

Specifically, we will be A, B together sorted according to their length, are considered in turn in descending sequence, consider Class A Class B consider string string.
For Class A string segment tree can be directly thrown into the position corresponding to its rank.
For class B series, we find the first half lcp> = | Bj | corresponding section, then the edge can be connected to this section.

Time complexity and space complexity is O (nlogn).

@accepted code@

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 200000;
struct edge{
    int to; edge *nxt;
}edges[80*MAXN + 5], *adj[45*MAXN + 5], *ecnt;
int ind[45*MAXN + 5];
void addedge(int u, int v) {
    edge *p = (++ecnt);
    p->to = v, p->nxt = adj[u], adj[u] = p;
    ind[v]++;
//  printf("! %d %d\n", u, v);
}
struct node{
    int l, r, id;
    node(int _l=0, int _r=0):l(_l), r(_r) {}
    int len() {return r - l + 1;}
    friend bool operator < (node x, node y) {return x.len() < y.len();}
}a[MAXN + 5], b[MAXN + 5];
char S[MAXN + 5];
int sa[MAXN + 5], rnk[MAXN + 5], c[MAXN + 5];
int nsa[MAXN + 5], nrnk[MAXN + 5];
int na, nb, m, lenS;
void get_sa(int n, int m) {
    for(int i=0;i<m;i++) c[i] = 0;
    for(int i=0;i<n;i++) c[S[i]]++;
    for(int i=1;i<m;i++) c[i] += c[i-1];
    for(int i=n-1;i>=0;i--) sa[--c[S[i]]] = i;
    rnk[sa[0]] = 0;
    for(int i=1;i<n;i++) rnk[sa[i]] = rnk[sa[i-1]] + (S[sa[i]] != S[sa[i-1]]);
    for(int k=1;rnk[sa[n-1]]!=n-1;k<<=1) {
        int cnt = 0;
        for(int i=n-k;i<n;i++) nsa[cnt++] = i;
        for(int i=0;i<n;i++)
            if( sa[i] >= k ) nsa[cnt++] = sa[i] - k;
        for(int i=0;i<n;i++) nrnk[i] = rnk[i];
        for(int i=0;i<n;i++) c[i] = 0;
        for(int i=0;i<n;i++) c[nrnk[i]]++;
        for(int i=1;i<n;i++) c[i] += c[i-1];
        for(int i=n-1;i>=0;i--) sa[--c[nrnk[nsa[i]]]] = nsa[i];
        rnk[sa[0]] = 0;
        for(int i=1;i<n;i++) rnk[sa[i]] = rnk[sa[i-1]] + (nrnk[sa[i]] != nrnk[sa[i-1]] || nrnk[sa[i]+k] != nrnk[sa[i-1]+k]);
    }
}
int ht[MAXN + 5];
void get_height(int n) {
    int k = 0;
    for(int i=0;i<n;i++) {
        if( rnk[i] == 0 ) ht[rnk[i]] = 0;
        else {
            if( k ) k--;
            while( S[i+k] == S[sa[rnk[i]-1]+k] )
                k++;
            ht[rnk[i]] = k;
        }
    }
}
int st[20][MAXN + 5], lg[MAXN + 5];
void get_st(int n) {
    for(int i=0;i<n;i++)
        st[0][i] = ht[i];
    for(int i=2;i<=n;i++)
        lg[i] = lg[i>>1] + 1;
    for(int j=1;j<20;j++) {
        int t = (1<<(j-1));
        for(int i=0;i+t<n;i++)
            st[j][i] = min(st[j-1][i], st[j-1][i+t]);
    }
}
int lcp(int l, int r) {
    if( l == r ) return MAXN;
    if( l > r ) swap(l, r); l++;
    int k = lg[r-l+1], p = (1<<k);
    return min(st[k][l], st[k][r-p+1]);
}
int ch[2][40*MAXN + 5], root, ncnt;
void link_edge(int rt, int l, int r, const int &ql, const int &qr, const int &x) {
    if( l > qr || r < ql || (!rt) ) return ;
    if( ql <= l && r <= qr ) {
        addedge(x, rt + na + nb);
        return ;
    }
    int mid = (l + r) >> 1;
    link_edge(ch[0][rt], l, mid, ql, qr, x);
    link_edge(ch[1][rt], mid + 1, r, ql, qr, x);
}
int insert(int rt, int l, int r, const int &p, const int &x) {
    int q = (++ncnt);
    ch[0][q] = ch[0][rt], ch[1][q] = ch[1][rt];
    if( l == r ) {
        if( rt ) addedge(q + na + nb, rt + na + nb);
        addedge(q + na + nb, x);
    }
    else {
        int mid = (l + r) >> 1;
        if( p <= mid ) ch[0][q] = insert(ch[0][rt], l, mid, p, x);
        else ch[1][q] = insert(ch[1][rt], mid + 1, r, p, x);
        if( ch[0][q] ) addedge(q + na + nb, ch[0][q] + na + nb);
        if( ch[1][q] ) addedge(q + na + nb, ch[1][q] + na + nb);
    }
    return q;
}
void get_lr(int ps, int len, int &l, int &r, const int &n) {
    int le, ri;
    le = rnk[ps], ri = n - 1;
    while( le < ri ) {
        int mid = (le + ri + 1) >> 1;
        if( lcp(rnk[ps], mid) >= len ) le = mid;
        else ri = mid - 1;
    }
    r = le;
    le = 0, ri = rnk[ps];
    while( le < ri ) {
        int mid = (le + ri) >> 1;
        if( lcp(rnk[ps], mid) >= len ) ri = mid;
        else le = mid + 1;
    }
    l = ri;
}
long long dp[45*MAXN + 5];
int val[MAXN + 5], que[45*MAXN + 5], s, t;
long long tsort() {
    long long ret = 0; s = 1, t = 0;
    for(int i=1;i<=ncnt+na+nb;i++) {
        if( !ind[i] ) que[++t] = i;
        dp[i] = 0;
    }
    while( s <= t ) {
        int f = que[s++];
        if( f <= na ) dp[f] += val[f];
        ret = max(ret, dp[f]);
        for(edge *p=adj[f];p;p=p->nxt) {
            ind[p->to]--;
            if( !ind[p->to] ) que[++t] = p->to;
            dp[p->to] = max(dp[p->to], dp[f]);
        }
    }
    if( t != ncnt + na + nb )
        return -1;
    else return ret;
}
void solve() {
    scanf("%s", S), lenS = strlen(S), ecnt = &edges[0];
    get_sa(lenS + 1, 128);
    get_height(lenS + 1);
    get_st(lenS + 1);
    scanf("%d", &na);
    for(int i=1;i<=na;i++)
        scanf("%d%d", &a[i].l, &a[i].r), a[i].id = i, val[i] = a[i].len();
    sort(a + 1, a + na + 1);
    scanf("%d", &nb);
    for(int i=1;i<=nb;i++)
        scanf("%d%d", &b[i].l, &b[i].r), b[i].id = i;
    sort(b + 1, b + nb + 1);
    int p = na, q = nb; root = ncnt = 0;
    while( p >= 1 && q >= 1 ) {
        if( a[p].len() >= b[q].len() )
            root = insert(root, 1, lenS, rnk[a[p].l-1], a[p].id), p--;
        else {
            int l, r; get_lr(b[q].l-1, b[q].len(), l, r, lenS + 1);
            link_edge(root, 1, lenS, l, r, b[q].id + na), q--;
        }
    }
    while( q >= 1 ) {
        int l, r; get_lr(b[q].l-1, b[q].len(), l, r, lenS + 1);
        link_edge(root, 1, lenS, l, r, b[q].id + na), q--;
    }
    scanf("%d", &m);
    for(int i=1;i<=m;i++) {
        int x, y; scanf("%d%d", &x, &y);
        addedge(x, y + na);
    }
    printf("%lld\n", tsort());
    for(int i=1;i<=na+nb+ncnt;i++)
        adj[i] = NULL, ind[i] = 0;
}
int main() {
    int T; scanf("%d", &T);
    while( T-- ) solve();
}

@details@

Note that a line segment interval tree node will be split into 2 * logn nodes instead of logn.
Although there are O (logn), but open array when it could not pay attention to what RE.

Guess you like

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