首页 > 题解 > bzoj 2780 [Spoj]8093 Sevenk Love Oimaster

bzoj 2780 [Spoj]8093 Sevenk Love Oimaster

Description

Oimaster and sevenk love each other.

But recently,sevenk heard that a girl named ChuYuXun was dating with oimaster.As a woman’s nature, sevenk felt angry and began to check oimaster’s online talk with ChuYuXun. Oimaster talked with ChuYuXun n times, and each online talk actually is a string.Sevenk asks q questions like this, “how many strings in oimaster’s online talk contain this string as their substrings?”

Input

There are two integers in the first line,
the number of strings n and the number of questions q.
And n lines follow, each of them is a string describing oimaster’s online talk.
And q lines follow, each of them is a question.
n<=10000, q<=60000
the total length of n strings<=100000,
the total length of q question strings<=360000

Output

For each question, output the answer in one line.

Sample Input

3 3

abcabcabc

aaa

aafe

abc

a

ca

Sample Output

1

3

1

题解

题意就是给n个串和m个串,求这m个串是n个串中多少个串的子串。

n个串建个广义后缀自动机,注意建的时候对于每个点标记一下这个点有多少个串用了这个点,多个串的化就外挂一个链表。

然后对每个询问串在自动机上匹配,匹配到的点其Parent树子树中的节点就可以包含这个串。我们把Parent树的dfs序找出来,那么这个题就转换成了hh的项链那个题,搞个树状数组就解决了。

这题一遍过样例一遍a,很爽

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200010
using namespace std;
struct Graph_Chain
{
    struct edge
    {
        int to,next;
    }e[N];
    int st[N],tot;
    void add(int x,int y)
    {
        e[++tot].next=st[x];
        e[tot].to=y,st[x]=tot;
    }
    int dfn[N],dfs_id,pos[N],low[N];
    void dfs(int now)
    {
        dfn[now]=++dfs_id,pos[dfs_id]=now;
        for (int i=st[now];i;i=e[i].next)
            dfs(e[i].to);
        low[now]=dfs_id;
    }
}g,chain;
struct asks
{
    int l,r,id;
}ask[N];
bool comp(asks a,asks b)
{
    return a.r<b.r;
}
struct SAM
{
    int dis[N<<1],fa[N<<1],ch[N<<1][26],sz,root,last;
    void init(){sz=1,root=1,last=root;}
    void insert(int x,int t)
    {
        int now=ch[last][x],pre=last;
        if (now)
            if (dis[now]==dis[pre]+1) last=now;
            else
            {
                int nows=++sz;dis[nows]=dis[pre]+1;
                memcpy(ch[nows],ch[now],sizeof ch[now]);
                fa[nows]=fa[now],fa[now]=nows;
                for (;pre && ch[pre][x]==now;pre=fa[pre]) ch[pre][x]=nows;
                last=nows;
            }
        else
        {
            now=++sz,dis[now]=dis[pre]+1;last=now;
            for (;pre && !ch[pre][x];pre=fa[pre]) ch[pre][x]=now;
            if (!pre) fa[now]=root;
            else if (dis[ch[pre][x]]==dis[pre]+1) fa[now]=ch[pre][x];
            else
            {
                int q=ch[pre][x],nows=++sz;dis[nows]=dis[pre]+1;
                memcpy(ch[nows],ch[q],sizeof ch[nows]);
                fa[nows]=fa[q],fa[q]=fa[now]=nows;
                for (;pre && ch[pre][x]==q;pre=fa[pre]) ch[pre][x]=nows;
            }
        }
        chain.add(last,t);
    }
    void ins(char s[],int t)
    {
        int len=strlen(s+1);
        last=root;
        for (int i=1;i<=len;i++)
            insert(s[i]-'a',t);
    }
    void match(char s[],int t)
    {
        int now=root,len=strlen(s+1);
        for (int i=1;i<=len;i++)
            if (ch[now][s[i]-'a'])
                now=ch[now][s[i]-'a'];
            else {now=0;break;}
        ask[t]=(asks){g.dfn[now],g.low[now],t};
    }
}sam;
struct BIT
{
    #define lowbit(x) (x&(-x))
    int c[N];
    void add(int x,int v)
    {
        if (!x) return;
        for (;x<=sam.sz;x+=lowbit(x)) c[x]+=v;
    }
    int sum(int x)
    {
        int ans=0;
        for (;x;x-=lowbit(x)) ans+=c[x];
        return ans;
    }
    int query(int l,int r)
    {
        return sum(r)-sum(l-1);
    }
    #undef lowbit
}bit;
int ans[N],vis[N],n,m;
char s[360010];
main()
{
    sam.init();
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%s",s+1),sam.ins(s,i);
    for (int i=1;i<=sam.sz;i++)
        g.add(sam.fa[i],i);
    g.dfs(1);
    for (int i=1;i<=m;i++)
        scanf("%s",s+1),sam.match(s,i);
    sort(ask+1,ask+1+m,comp);
    int top;
    for (top=1;top<=m&&!ask[top].l;top++);
    for (int i=1;i<=sam.sz;i++)
    {
        int now=g.pos[i];
        for (int j=chain.st[now];j;j=chain.e[j].next)
        {
            int v=chain.e[j].to;
            bit.add(i,1);
            if (vis[v]) bit.add(vis[v],-1);
            vis[v]=i;
        }
        for (;ask[top].r==i;top++)
            ans[ask[top].id]=bit.query(ask[top].l,ask[top].r);
    }
    for (int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
}