loj6031. "Yali training 2017 Day1" string

The meaning of problems

Noting the length of the query string \ (K \) is given, while \ (\ SUM \ Limits len_w KQ = \ leqslant10. 5 ^ \) , we found \ (k, q \) between one another must be large will be small, so we \ (k \) Category talk:
first, be sure to pair \ (s \) to build a suffix automaton, the maintenance on each point \ (endpos \) size of the collection.

\(k\geqslant\sqrt{n}\)

At this time \ (Q \ leqslant \ n-sqrt {} \) , we directly \ (the SAM \) matching violent \ (W \) , identify all \ (W \) prefix corresponding to a node, then enumeration interrogation, multiplying jump \ (w [l_i ... r_i] \) of this node, the coupled node answers \ (endpos \) set size to.

\(k<\sqrt{n}\)

At this time \ (m \) species group interrogation little, we can enumerate \ (W \) of all sub-strings, it is calculated \ ([l, r] \ ) the number of occurrences of this interrogation interval, multiplied by its answer added to the answer.

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define pii pair<int,int>
#define mkp make_pair
#define fir first
#define sec second
const int maxn=2e5+10;
const int maxt=410;
int n,m,Q,K,tot,cnt_edge,t;
int head[maxn],size[maxn],pos[maxn],posl[maxn];
int f[maxn][18];
char s[maxn];
inline int read()
{
    char c=getchar();re int res=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    return res*f;
}
struct edge{int to,nxt;}e[maxn];
inline void add_edge(int u,int v)
{
    e[++cnt_edge].nxt=head[u];
    head[u]=cnt_edge;
    e[cnt_edge].to=v;
}
struct Query{int l,r;}qr[maxn];
struct SAM
{
    int last,tot;
    int fa[maxn],len[maxn];
    int ch[maxn][26];
    SAM(){last=tot=1;}
    inline void add(int c)
    {
        re int now=++tot;len[now]=len[last]+1;
        re int p=last;last=now;
        while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
        if(!p){fa[now]=1;return;}
        re int q=ch[p][c];
        if(len[q]==len[p]+1)fa[now]=q;
        else
        {
            re int nowq=++tot;len[nowq]=len[p]+1;
            memcpy(ch[nowq],ch[q],sizeof(ch[q]));
            fa[nowq]=fa[q];fa[q]=fa[now]=nowq;
            while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
        }
    }
}sam;
void dfs(int x)
{
    for(re int i=1;i<=17;i++)f[x][i]=f[f[x][i-1]][i-1];
    for(re int i=head[x];i;i=e[i].nxt)
    {
        re int y=e[i].to;
        f[y][0]=x;dfs(y);
        size[x]+=size[y];
    }
}
inline void solve1()
{
    vector<int>a[maxt][maxt];
    for(int i=1;i<=m;i++)a[qr[i].l][qr[i].r].push_back(i);
    while(Q--)
    {
        scanf("%s",s+1);
        int l=read()+1,r=read()+1;
        ll res=0;
        for(int i=1;i<=K;i++)
            for(int j=i,now=1;j<=K;j++)
            {
                now=sam.ch[now][s[j]-'a'];
                if(!now)break;
                int ql=lower_bound(a[i][j].begin(),a[i][j].end(),l)-a[i][j].begin();
                int qr=upper_bound(a[i][j].begin(),a[i][j].end(),r)-a[i][j].begin();
                res+=1ll*(qr-ql)*size[now];
            }
        printf("%lld\n",res);
    }
}
inline int find(int l,int r)
{
    re int now=pos[r];
    for(re int i=17;~i;i--)if(sam.len[f[now][i]]>=min(r-l+1,posl[r]))now=f[now][i];
    return now;
}
inline int solve(int l,int r)
{
    if(!pos[r]||posl[r]<(r-l+1))return 0;;
    re int now=find(l,r);
    if(sam.len[now]>=r-l+1)return size[now];
    else return 0;
}
inline void solve2()
{
    while(Q--)
    {
        scanf("%s",s+1);
        re int l=read()+1,r=read()+1;
        re int now=1,nowl=0,res=0;
        for(re int i=1;i<=K;i++)
        {
            re int c=s[i]-'a';
            while(!sam.ch[now][c]&&now)now=sam.fa[now],nowl=sam.len[now];
            if(!now){now=1;pos[i]=1;nowl=0;posl[i]=0;continue;}
            now=sam.ch[now][c];pos[i]=now;
            nowl++;posl[i]=nowl;
        }   
        for(re int i=l;i<=r;i++)res+=solve(qr[i].l,qr[i].r);
        printf("%d\n",res);
    }
}
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    n=read(),m=read(),Q=read(),K=read();t=330;
    scanf("%s",s+1);
    for(re int i=1;i<=n;i++)sam.add(s[i]-'a'),size[sam.last]=1;
    for(re int i=2;i<=sam.tot;i++)add_edge(sam.fa[i],i);
    dfs(1);
    for(re int i=1;i<=m;i++)qr[i].l=read()+1,qr[i].r=read()+1;
    if(K<=t)solve1();
    else solve2();
    return 0;
} 

Guess you like

Origin www.cnblogs.com/nofind/p/12149765.html