MYF

HDU 5384 Danganronpa

题目链接

HDU 5384

方法:ac自动机 变形

题目分析

题目大意

n个字符串,m个子串,问每个字符串中有多少个子串,可以重复

解析

ac自动机,但是删掉了查询时的一行代码,有待深入理解。

ac自动机详解链接

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1)
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define IN freopen("input.txt","r",stdin);
#define OUT freopen("output.txt","w",stdout);
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long ll;
using namespace std;
const int maxn=1000+5;
const int mod=1000000007;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
struct trie
{
int next[500010][26],fail[500010],ed[500010];
int root,L;
int newnode()
{
for(int i = 0; i < 26; i++)
next[L][i] = -1;
ed[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = 0; i < len; i++)
{
if(next[now][buf[i]-'a'] == -1)
next[now][buf[i]-'a'] = newnode();
now = next[now][buf[i]-'a'];
}
ed[now]++;
}
void build()
{
queue<int> q;
fail[root] = root;
for(int i = 0; i < 26; i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
q.push(next[root][i]);
}
while(!q.empty())
{
int now = q.front();
q.pop();
for(int i = 0; i < 26; i++)
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
q.push(next[now][i]);
}
}
}
int query(char buf[])
{
int len = strlen(buf);
int now = root;
int res = 0;
for(int i = 0; i < len; i++)
{
now = next[now][buf[i]-'a'];
int temp = now;
while(temp != root)
{
res += ed[temp];
temp = fail[temp];
}
}
return res;
}
void Debug()
{
for(int i = 0; i < L; i++)
{
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],ed[i]);
for(int j = 0; j < 26; j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
};
char buf[1000010];
trie ac;
char ss[100005][10005];
int main()
{
int t;
int n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ac.init();
for (int i=0; i<n; i++) {
scanf("%s",ss[i]);
}
for(int i = 0; i < m; i++)
{
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
for (int i=0; i<n; i++) {
printf("%d\n",ac.query(ss[i]));
}
}
return 0;
}