bzoj 2780 [Spoj]8093 Sevenk Love Oimaster

http://www.elijahqi.win/archives/3192
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, s
evenk felt angry and began to check oimaster’s online talk with ChuYuXun. Oimaster talked with Ch
uYuXun 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?”
有n个大串和m个询问,每次给出一个字符串s询问在多少个大串中出现过
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
HINT

Source

鸣谢duan2提供译文

将文本串建广义SAM 然后将询问离线

每次询问相当于一棵子树然后 将询问按照子树的结束节点从小到大排序 然后 一边询问一边做 每次做的时候相当于把我这部分改一下 把我的影响改掉 因为我的子树里不可能有我的贡献了同时再把我的贡献加上 即从上一次这个串出现的位置到这次所在的位置都加上1即可 等到我这个询问的子树里的内容都做完了我直接查询我子树开始的位置的值即可

#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;string ss;
int ch[N<<1][26],root=1,n,m,last=1,cnt=1,q,len[N<<1],fa[N<<1];
vector<int>c[N<<1];int s[N<<1],lst[N<<1],ans[N];
inline void insert1(int x,int id){
    int p=last; 
    if(ch[p][x]){
        int q=ch[p][x];if (len[p]+1==len[q]){c[q].push_back(id);last=q;return;}
        int nq=++cnt;memcpy(ch[nq],ch[q],sizeof(ch[q]));fa[nq]=fa[q];len[nq]=len[p]+1;
        fa[q]=nq;for (;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;c[nq].push_back(id);last=nq;return;
    }
    int np=++cnt;len[np]=len[p]+1;c[np].push_back(id);
    for (;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
    if (!p) fa[np]=root;else{
        int q=ch[p][x];if (len[p]+1==len[q]) fa[np]=q;else{
            int nq=++cnt;memcpy(ch[nq],ch[q],sizeof(ch[q]));fa[nq]=fa[q];fa[q]=fa[np]=nq;
            len[nq]=len[p]+1;for (;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
        }
    }last=np;
}int top;
inline void add(int x,int v){for (;x<=top;x+=x&-x) s[x]+=v;}
inline int query(int x){static int tmp;for (tmp=0;x;x-=x&-x) tmp+=s[x];return tmp;}
struct node{
    int y,next;
}data[N<<1];
struct node1{int l,r,id;}qr[N];int num,h[N<<1],in[N<<1],out[N<<1],dfn[N<<1];
inline bool cmp(const node1 &a,const node1 &b){return a.r<b.r;}
inline void insert2(int x,int y){data[++num].y=y;data[num].next=h[x];h[x]=num;}
inline void dfs(int x){
    in[x]=++num;dfn[num]=x;
    for (int i=h[x];i;i=data[i].next) dfs(data[i].y);
    out[x]=num;
}
inline void init(int id){
    cin>>ss;int p=root;
    for (int i=0;i<ss.size();++i){
        p=ch[p][ss[i]-'a'];if (!p) return;
    }qr[++cnt].l=in[p];qr[cnt].r=out[p];qr[cnt].id=id;
}
int main(){
    freopen("bzoj2780.in","r",stdin);
    std::ios::sync_with_stdio(0);cin>>n>>q;
    for (int i=1;i<=n;++i) {cin>>ss;last=root;
        for (int j=0;j<ss.size();++j) insert1(ss[j]-'a',i);
    }int now=1;
    for (int i=2;i<=cnt;++i) insert2(fa[i],i);num=0;dfs(1);top=cnt;
    cnt=0;for (int i=1;i<=q;++i) init(i);sort(qr+1,qr+cnt+1,cmp);
    for (int i=1;i<=cnt;++i){
        while(now<=qr[i].r){static int p;p=dfn[now];
            for (int j=0;j<c[p].size();++j){
                add(now+1,-1);add(lst[c[p][j]]+1,1);lst[c[p][j]]=now;
            }++now;
        }ans[qr[i].id]=query(qr[i].l);
    }
    for (int i=1;i<=q;++i) printf("%d\n",ans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值