bzoj 2780: [Spoj]8093 Sevenk Love Oimaster (广义后缀自动机)

来源:互联网 发布:java n的阶乘 编辑:程序博客网 时间:2024/05/16 08:14

2780: [Spoj]8093 Sevenk Love Oimaster

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 738  Solved: 257
[Submit][Status][Discuss]

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

HINT

Source

[Submit][Status][Discuss]


题解:广义后缀自动机

题目大意:给出n个原串,再给出m个查询串。求每个查询串出现在了多少原串中。

建立后缀自动机,所谓广义就是将几个串建立在同一个自动机上,每次加入一个新串的时候,将last恢复到root,然后其他照常做就可以了。

如何统计每个状态出现在了多少原串中呢?我们对于每个状态维护两个值size,nxt。nxt存储的是上一个到达这个状态的串是哪个原串,如果与当前的原串相同就不更新。如果不相同就size++.根据后缀自动机的性质,当前点的值改变,parent链上的信息都需要更改,链上nxt的值应该是区间分布的,所以只要找到一个nxt等于当前的点,就可以不用再往前找了。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define N 200003using namespace std;int ch[N][30],fa[N],l[N],n,m,len;int r[N],v[N],cnt,np,p,nq,q,last,root,nxt[N],now,size[N];char s[N];void extend(int x){int c=s[x]-'a';p=last; np=++cnt; last=np; l[np]=l[p]+1;for (;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;if (!p) fa[np]=root;else {q=ch[p][c];if (l[q]==l[p]+1) fa[np]=q;else {nq=++cnt; l[nq]=l[p]+1;memcpy(ch[nq],ch[q],sizeof ch[nq]); size[nq]=size[q]; nxt[nq]=nxt[q];fa[nq]=fa[q];fa[q]=fa[np]=nq;for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;}}for (;np;np=fa[np])  if (nxt[np]!=now) { size[np]++; nxt[np]=now; } else break;}int main(){freopen("a.in","r",stdin);freopen("my.out","w",stdout);scanf("%d%d",&n,&m);root=++cnt;for(int i=1;i<=n;i++) {scanf("%s",s+1);last=root;len=strlen(s+1);now=i;for (int j=1;j<=len;j++)  extend(j);}for (int i=1;i<=m;i++) {scanf("%s",s+1);len=strlen(s+1);p=root;for (int j=1;j<=len;j++)  p=ch[p][s[j]-'a'];    printf("%d\n",size[p]);}}



0 0
原创粉丝点击