Brush [Title] [NOI2018] Your name LuoguP4770 / LOJ2720

topic

LOJ2720 PSloj data better at.
LuoguP4770
each given two strings S and T, the first interrogation of a number of different sub-string string is not a second substrings.
Each query will give a different S, and T is a substring of a string start input (input \ ([l, r] \ ) described).
\ (| S |, | T | <= 5 \ times10 ^ 5, \ sum | S | <= 10 ^ 6 \)

Thinking

Data structure, ideology

  • Segment tree merger (persistable)
  • Suffix automata

    True ideas

  • Several conventions statement: endpos represents the end position of the substring suffix automaton node represents, len indicates the length of the longest sub-string of the node represents, link represents a suffix link.
  • First, to simplify the problem: Consider for each prefix string S, can determine how much the longest matched string T. Shorter than this would certainly not. Longer than this length, it is possible to re-use ParentTree. (Length only get yourself this node, the rest get on that node suffix link points)
  • Tidy, we found that we ran on the string S as long as the matching length T suffix automaton, then the match length suffix automaton S placed on the number of different sub-strings ran.
  • For example, the node 4 len is 8, link point No. 3, No. 3, len is the length of the matching node is 4,4 number 3. That can match length number 3 is also 3. In answer to No. 4 by 4, add 1 answer at No. 3. (Because there may be other nodes point 3, so we can not directly count 4)
  • Then consider how to answer multiple sets of questions.
  • We found that the problem lies in the S on T matching the length of the run this step. Because you will spot built SAM T out.
  • So we consider the use of SAM total input string beginning to achieve matching.
  • When we matched when a node (matched \ (CNT \) bits), the length of the real match, the node is in endpos [l, R & lt] this range, farthest from the endpos l to l, distance, and \ (CNT \) take \ (min \) results.
  • Ever since, we have to maintain it endpos collection. This can be combined with the tree line. But note that, when we should have been merged to create a new point (can be persistent), or else will destroy previously quite good endpos collection.

    Little attention

  • When we calculate the length of the match, if the current point \ ([l, r] \ ) distance l in the rightmost endpos to, than his small link in len, then we should jump to the link. As this may gain new endpos, more in the right place.
  • Sand sculpture of lojAC after cross Luogu, find RE. Finally, this should not have proved to be a function return values, the authors write int, but at the same time, there is no return, resulting in the valley do not give too upright Luo.

    Code

#include<bits/stdc++.h>
#define LL long long
#define MAXN 500000
using namespace std;
template<typename T>void Read(T &cn)
{
    char c;int sig = 1;
    while(!isdigit(c = getchar()))if(c == '-')sig = -1; cn = c-48;
    while(isdigit(c = getchar()))cn = cn*10+c-48; cn*=sig;
}
template<typename T>void Write(T cn)
{
    if(cn<0) {putchar('-'); cn = 0-cn; }
    int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
    while(cn)wei++,cm = cm*10+cn%10,cn/=10;
    while(wei--)putchar(cm%10+48),cm/=10;
    putchar(cx+48);
}
int he[MAXN+1],xu[MAXN*2+1];
struct Seg{
    struct node{
        int ls,rs,da;
        void qing() {ls = rs = da = 0; }
    };
    node t[MAXN*60+1];
    int tlen;
    int ro[MAXN*2+1];
    void build() {tlen = 0; t[0].qing(); }
    void jia(int &cn,int cm,int l,int r)
    {
        if(!cn)t[cn = ++tlen].qing();
        if(l == r) {t[cn].da = cm; return; }
        int zh = (l+r)>>1;
        if(cm <= zh)jia(t[cn].ls,cm,l,zh); else jia(t[cn].rs,cm,zh+1,r);
        t[cn].da = max(t[t[cn].ls].da,t[t[cn].rs].da);
    }
    int cha(int cn,int cm,int l,int r)
    {
        if(!cn)return 0;
        if(r <= cm)return t[cn].da;
        int zh = (l+r)>>1;
        if(cm > zh)return max(cha(t[cn].rs,cm,zh+1,r),t[t[cn].ls].da);
        else return cha(t[cn].ls,cm,l,zh);
    }
    void bing(int &cn,int cm1,int cm2,int l,int r)
    {
        if(!cm1 && !cm2)return;
        if(!cm1) {cn = cm2; return; }
        if(!cm2) {cn = cm1; return; }
        cn = ++tlen;
        t[cn].da = max(t[cm1].da,t[cm2].da);
        if(l == r)return;
        bing(t[cn].ls,t[cm1].ls,t[cm2].ls,l,(l+r)>>1);
        bing(t[cn].rs,t[cm1].rs,t[cm2].rs,((l+r)>>1)+1,r);
    }
}T;
struct SAM{
    struct node{
        int link,len,ch[26];
        int edp,f;
        void qing() {link = len = 0; memset(ch,0,sizeof(ch)); }
    };
    node t[MAXN*2+1];
    int tlen,last;
    void build() {t[tlen = last = 1].qing(); }
    void jia(int cn,int cm)
    {
        int cur = ++tlen;
        t[cur].qing();
        t[cur].edp = cm;
        t[cur].len = t[last].len+1;
        int p = last;
        for(;p && !t[p].ch[cn];p = t[p].link)t[p].ch[cn] = cur;
        if(!p)t[cur].link = 1;
        else{
            int q = t[p].ch[cn];
            if(t[p].len +1 == t[q].len)t[cur].link = q;
            else{
                int cln = ++tlen;
                t[cln] = t[q]; t[cln].edp = 0;
                t[cln].len = t[p].len+1;
                t[cur].link = t[q].link = cln;
                for(;p && t[p].ch[cn] == q;p = t[p].link)t[p].ch[cn] = cln;
            }
        }
        last = cur;
    }
    void pro_edp()
    {
        T.build();
        for(int i = 0;i<=t[last].len;i++)he[i] = 0;
        for(int i = 1;i<=tlen;i++)he[t[i].len]++;
        for(int i = 1;i<=t[last].len;i++)he[i] += he[i-1];
        for(int i = 1;i<=tlen;i++)xu[he[t[i].len]--] = i;
        for(int i = tlen;i>=1;i--)
        {
            if(t[xu[i]].edp)T.jia(T.ro[xu[i]],t[xu[i]].edp,1,t[last].len);
            if(t[xu[i]].link)T.bing(T.ro[t[xu[i]].link],T.ro[t[xu[i]].link],T.ro[xu[i]],1,t[last].len);
        }
    }
    int tongji(int n,int l,int r,int ans[],char c[])
    {
        int dang = 1,xian = 0;
        for(int i = 1;i<=n;i++)
        {
            int lin = t[dang].ch[c[i]-'a'],lin2;
            while(dang != 1 && (!lin || T.cha(T.ro[lin],r,1,t[last].len) < l))dang = t[dang].link,lin = t[dang].ch[c[i]-'a'],xian = min(xian,t[dang].len);
            if(lin && T.cha(T.ro[lin],r,1,t[last].len) >= l)dang = lin,xian++; lin2 = T.cha(T.ro[dang],r,1,t[last].len);
            while(dang != 1 && t[t[dang].link].len >= lin2 - l+1)dang = t[dang].link,xian = t[dang].len,lin2 = T.cha(T.ro[dang],r,1,t[last].len);
            ans[i] = min(xian,lin2-l+1);
        }
    }
    LL jisuan(int a[])
    {
        for(int i = 0;i<=t[last].len;i++)he[i] = 0;
        for(int i = 1;i<=tlen;i++)he[t[i].len]++,t[i].f = 0;
        for(int i = 1;i<=t[last].len;i++)he[i] += he[i-1];
        for(int i = 1;i<=tlen;i++)xu[he[t[i].len]--] = i;
        LL guo = 0;
        for(int i = tlen;i>=1;i--)
        {
            if(t[xu[i]].edp)t[xu[i]].f = max(a[t[xu[i]].edp],t[xu[i]].f);
            t[xu[i]].f = min(t[xu[i]].f,t[xu[i]].len);
            guo = guo + t[xu[i]].len - max(t[xu[i]].f,t[t[xu[i]].link].len);
            t[t[xu[i]].link].f = max(t[t[xu[i]].link].f,t[xu[i]].f);
        }
        return guo;
    }
}S1,S2;
int clen,dlen;
char c[MAXN*2+1],d[MAXN*2+1];
int a[MAXN*2+1];
int n;
void getit(char c[],int &n)
{
    while(!isalpha(c[1] = getchar())); n = 1;
    while(isalpha(c[++n] = getchar())); n--; 
}
int main()
{
//  freopen("name1.in","r",stdin);
//  freopen("name1.out","w",stdout);
    getit(c,clen); S1.build();
    for(int i = 1;i<=clen;i++)S1.jia(c[i]-'a',i); S1.pro_edp();
    Read(n);
    while(n--)
    {
        getit(d,dlen); int bx,by; Read(bx); Read(by);
        S1.tongji(dlen,bx,by,a,d);
        S2.build(); for(int i = 1;i<=dlen;i++)S2.jia(d[i]-'a',i);
        Write(S2.jisuan(a)); putchar('\n');
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/czyarl/p/11356317.html