【BZOJ2780】Sevenk Love Oimaster【广义后缀自动机】

题意

  给出你n个字符串和q个查询,每个查询给出一个字符串s,对于每个查询你都要输出这个字符串s在上面多少个字符串中出现过。

分析

  广义后缀自动机的裸题。建好SAM以后再跑一遍得到每个状态的ocu和las。然后对于每个查询的字符串,跑到那个状态然后输出那个状态的ocu就可以了。

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 const int maxn=201000;
 8 struct state{
 9     int len,link,ocu,las;
10     int next[26];
11 }st[maxn];
12 int N,Q,n;
13 int last,cur,sz;
14 char s[maxn];
15 string S[100000+5];
16 void init(){
17     sz=1;
18     cur=last=0;
19     st[0].link=-1;
20     st[0].len=0;
21 }
22 void build_sam(int c){
23     cur=sz++;
24     st[cur].len=st[last].len+1;
25     int p;
26     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link){
27             st[p].next[c]=cur;
28     }
29     if(p==-1)
30         st[cur].link=0;
31     else{
32         int q=st[p].next[c];
33         if(st[q].len==st[p].len+1)
34             st[cur].link=q;
35         else{
36             int clone=sz++;
37             st[clone].len=st[p].len+1;
38             st[clone].link=st[q].link;
39             for(int i=0;i<26;i++)
40                 st[clone].next[i]=st[q].next[i];
41             for(;p!=-1&&st[p].next[c]==q;p=st[p].link)
42                 st[p].next[c]=clone;
43             st[cur].link=st[q].link=clone;
44         }
45     }
46     last=cur;
47 }
48 
49 int main(){
50     scanf("%d%d",&N,&Q);
51     init();
52     for(int i=1;i<=N;i++){
53         scanf("%s",s);
54         S[i]=(string)s;
55         n=strlen(s);
56         for(int j=0;j<n;j++){
57             build_sam(s[j]-'a');
58         }
59         last=0;
60     }
61 
62     for(int i=1;i<=N;i++){
63         int u=0;
64         for(int j=0;j<S[i].length();j++){
65             u=st[u].next[S[i][j]-'a'];
66             int p=u;
67             while(p!=-1&&st[p].las!=i){
68                 st[p].ocu++;
69                 st[p].las=i;
70                 p=st[p].link;
71             }
72         }
73     }
74 
75     for(int q=1;q<=Q;q++){
76         scanf("%s",s);
77         n=strlen(s);
78         int u=0,flag=1;
79         for(int i=0;i<n;i++){
80             if(st[u].next[s[i]-'a']==0){
81                 flag=0;
82                 break;
83             }
84             u=st[u].next[s[i]-'a'];
85         }
86         if(!flag){
87             printf("0\n");
88         }else
89         printf("%d\n",st[u].ocu);
90     }
91 
92 return 0;
93 }
View Code

 

posted @ 2018-11-01 20:16  蒟蒻LQL  阅读(221)  评论(0编辑  收藏  举报