bzoj5417 / luoguP4770 [NOI2018] your name (suffix automaton + segment tree merger)

bzoj Luogu

Given a string S $ $ $ Q $ times and asked each time a query string $ T $ how many different sub-string is not the essence of $ S [l, r] $ substring.

Problem solution time

With on a question a bit like Ha.

But this time you want to match the $ T $ on $ S $.

Let's different every time regardless of the selected segment $ S $, we assume that we have built the SAM $ S $ segments selected (that is, before it 68pts)

We directly put up the $ T $ match, maintenance is now the longest length $ lnow $ on the match, when $ px $ skip $ tranc $ $ lnow ++ $,

When a mismatch PX $ $ skip to $ pre $, $ lnow $ modify the corresponding point $ len $.

But obviously not every time to re-build it again $ S $ of SAM.

So consider the above matching operation can be queried at $ [l, r] at some point within the range of $ whether $ endpos $.

Write a segment tree merge like.

At this time, then the above matching operation "mismatched" steps are required to change it.

Normal is modified directly after the jump to $ lnow $ $ pre $, but not here.

Because: Suppose we matched a point $ x $, $ ch $ the string $ T $, $ lnow $ known,

We want to query is $ tranc [x] [ch] $ of $ [l + lnow, r] $ interval.

So into $ lnow-- $ mismatch until $ lnow == len [pre [x]] $ when jumping $ pre $.

Obviously this match is still $ O (nlogn) $, the log from the tree line.

Then get away.

Matching the $ I $ characters provided on the $ T $ $ lnow = ma [i] $,

The $ ans = \ Sigma (each node on the SAM T) len [x] -max (len [pre [x]], ma [ip [x]]) $

($ Ip [x] $ $ X $ refers to the point on which the TSAM one corresponding to the character of $ T $)

Ugly package -1000

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
namespace RKK
{
const int N=2000011;
int TAT;
char s0[N],s1[N];int l0,l1;
int rt[N],tcnt,lson[N*44],rson[N*44];
struct sumireko{int to,ne;}e[N];int he[N],ecnt;
void addline(int f,int t){e[++ecnt].to=t;e[ecnt].ne=he[f],he[f]=ecnt;}
void insert(int x,int &px,int pl,int pr)
{
    if(!px) px=++tcnt;
    if(pl==pr) return;
    int pm=pl+pr>>1;
    if(x<=pm) insert(x,lson[px],pl,pm);
    else insert(x,rson[px],pm+1,pr);
}
int merge(int px,int py,int pl,int pr)
{
    if(!px||!py) return px|py;
    int pz=++tcnt;
    if(pl!=pr)
    {
        int pm=pl+pr>>1;
        lson[pz]=merge(lson[px],lson[py],pl,pm);
        rson[pz]=merge(rson[px],rson[py],pm+1,pr);
    }
    return pz;
}
int query(int l,int r,int px,int pl,int pr)
{
    if(l>r||!px) return 0;
    if(l<=pl&&r>=pr) return 1;
    int pm=pl+pr>>1;
    int ret=0;
    if(l<=pm) ret|=query(l,r,lson[px],pl,pm);
    if(r>pm) ret|=query(l,r,rson[px],pm+1,pr);
    return ret;
}
struct remilia{int tranc[26],len,pre;};
int ma[N];
struct sakuya
{
    remilia s[N];
    int ip[N];
    int fin,size;
    sakuya(){fin=size=1;}
    void set(){memset(s,0,sizeof(remilia)*(size+10)),memset(ip,0,sizeof(int)*(size+10)),fin=size=1;}
    void ins(int ch,int i=0)
    {
        int npx,npy,lpx,lpy;
        npx=++size;
        s[npx].len=s[fin].len+1;ip[npx]=i;
        for(lpx=fin;lpx&&!s[lpx].tranc[ch];lpx=s[lpx].pre) s[lpx].tranc[ch]=npx;
        if(!lpx) s[npx].pre=1;
        else
        {
            lpy=s[lpx].tranc[ch];
            if(s[lpy].len==s[lpx].len+1) s[npx].pre=lpy;
            else
            {
                npy=++size;
                s[npy]=s[lpy],ip[npy]=ip[lpy];
                s[npy].len=s[lpx].len+1;
                s[npx].pre=s[lpy].pre=npy;
                while(s[lpx].tranc[ch]==lpy)
                {
                    s[lpx].tranc[ch]=npy;
                    lpx=s[lpx].pre;
                }
            }
        }
        fin=npx;
    }
    void dfs(int x)
    {
        for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to) dfs(t),rt[x]=merge(rt[x],rt[t],1,l0);
    }
    void work()
    {
        for(int i=2;i<=size;i++) addline(s[i].pre,i);
        dfs(1);
    }
}sam,sam1;
void work(int l,int r)
{
    sam1.set();
    for(int i=1;i<=l1;i++) sam1.ins(s1[i]-'a',i);
    int px=1,lnow=0;
    for(int i=1;i<=l1;i++)
    {
        while(px!=1&&!query(l+lnow,r,rt[sam.s[px].tranc[s1[i]-'a']],1,l0))
        {
            lnow--;
            if(lnow==sam.s[sam.s[px].pre].len) px=sam.s[px].pre;
        }
        if(query(l+lnow,r,rt[sam.s[px].tranc[s1[i]-'a']],1,l0))
        {
            lnow++;
            px=sam.s[px].tranc[s1[i]-'a'];
        }
        ma[i]=lnow;
    }
    lint ans=0;
    for(int i=2;i<=sam1.size;i++) ans+=max(0,sam1.s[i].len-max(sam1.s[sam1.s[i].pre].len,ma[sam1.ip[i]]));
    printf("%lld\n",ans);
    memset(ma,0,sizeof(int)*(l1+5));
}
int Iris()
{
    scanf("%s",s0+1),l0=strlen(s0+1);
    for(int i=1;i<=l0;i++) sam.ins(s0[i]-'a'),insert(i,rt[sam.fin],1,l0);
    sam.work();
    scanf("%d",&TAT);
    for(int rkk=1,l,r;rkk<=TAT;rkk++)
    {
        scanf("%s%d%d",s1+1,&l,&r),l1=strlen(s1+1);
        work(l,r);
    }
    return 0;
}
}
int main(){return RKK::Iris();}

Guess you like

Origin www.cnblogs.com/rikurika/p/12079303.html