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 OutputFor each question, output the answer in one line.Sample Input3 3 abcabcabc aaa aafe abc a caSample Output
1 3 1
题意:
给定一些模板串,询问每个匹配串在多少个模板串里出现过。
思路:
后缀数组办法:
全部模板串连接在一起SA排序,SA数组附件的串里面去验证原串,还没写,我说不清楚,大概是后缀数组+RMQ处理。
后缀自动机办法:
1,广义后缀自动机+dfs序列+。。。
2,后缀自动机+标记,对于每个新的后缀集合np,标记它最近出现的原串,对每个模板串出现的新串的数量++。(目前发现最快的版本,如下)
经验:
- 与普通的后缀自动机不同的是,广义后缀自自动机在加入一个新串的时候,从root开始。
- 为了记录每个状态在哪些串出现过,会在每个np向上传递,我的代码是用的没加一个字符,向上传递一次。也可以用bitset记录在哪里出现过等到加完所有字符串后再拓扑排序,然后“亦或”向上传递。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define N 200003 using 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() { 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 ",size[p]); } }