hdu5853 (后缀自动机)

Problem Jong Hyok and String

题目大意

  给你n个字符串,有q个询问。

  定义set(s)={(i,j)} 表示 s在第i个字符串中出现,且末尾位置为j。

  对于一个询问,求set(Qi)=set(t) ,t的数量。

  (n,q<=10^5 , 字符串总长<=10^5)

解题分析

  直接将n个串塞进一个后缀自动机里面。

  对于一个询问串qi,找到其在后缀自动机中出现的位置j。

  则答案为len[j] - len[fail[j]] 。 (具体为什么还需要好好斟酌一下)

参考程序

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 #define V 100008
 7 int ans[V];
 8 struct sam{
 9     int nt[V*2][26],f[V*2],a[V*2],rig[V*2];
10     int last,sum,len;
11     int p,q,np,nq;
12 
13     void clear(){
14         memset(f,-1,sizeof(f));
15         memset(a,0,sizeof(a));
16         memset(nt,-1,sizeof(nt));
17         last = sum = len=0;
18     }
19     void insert(int ch){
20         len++;
21         if (~nt[last][ch] && a[nt[last][ch]]==len){
22             last=nt[last][ch]; return;
23         }
24         p=last; last=np=++sum; a[np]=a[p]+1; rig[np]=1;
25         for (;~p && !~nt[p][ch];p=f[p]) nt[p][ch]=np;
26         if (p==-1) f[np]=0;
27         else
28         {
29             q=nt[p][ch];
30             if (a[q]==a[p]+1) f[np]=q;
31             else
32             {
33                 nq=++sum; a[nq]=a[p]+1;
34                 memcpy(nt[nq],nt[q],sizeof(nt[q]));
35                 f[nq]=f[q];
36                 f[q]=f[np]=nq;
37                 for (;~p && nt[p][ch]==q;p=f[p]) nt[p][ch]=nq;
38             }
39         }
40     }
41     int work(char *s,int l){
42         int now=0;
43         for (int i=1;i<=l;i++){
44             if (nt[now][s[i]-'a']==-1) return 0;
45             now=nt[now][s[i]-'a'];  
46         }
47         return a[now]-a[f[now]];
48     }
49 }sam;
50 
51 char str[V];
52 void work(){
53     sam.clear();
54     int n,m;
55     scanf("%d %d",&n,&m);
56     for (int i=1;i<=n;i++){
57         sam.len=sam.last=0;
58         scanf("%s",str+1);
59         int len=strlen(str+1);
60         for (int j=1;j<=len;j++) sam.insert(str[j]-'a');
61     }
62     for (int i=1;i<=m;i++){
63         scanf("%s",str+1);
64         int len=strlen(str+1);
65         printf("%d\n",sam.work(str,len));   
66     }
67 }
68 
69 int main(){
70     int T;
71     scanf("%d",&T);
72     for (int t=1;t<=T;t++){
73         printf("Case #%d:\n",t );
74         work();
75     }
76     return 0;
77 }
View Code

 

posted @ 2016-08-16 22:53  rpSebastian  阅读(679)  评论(0编辑  收藏  举报