-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAho_Corasick.cpp
More file actions
143 lines (130 loc) · 3.39 KB
/
Copy pathAho_Corasick.cpp
File metadata and controls
143 lines (130 loc) · 3.39 KB
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
136
137
138
139
140
141
142
143
/**********************************************************
Aho_Corasick Algorithm
~Applications:
*Find the occurrence of all string from a given set in a text
*Find all strings from a given set in a text
*Finding the lexicographical smallest string of a given length that doesn't match any given strings
*Finding the shortest string containing all given strings
*Finding the lexicographical smallest string of length L containing k strings
**********************************************************/
// problem: Substring Frequency (II) LightOJ - 1427
// http://codeforces.com/contest/963/problem/D
#include<bits/stdc++.h>
using namespace std;
#define MX 250005
#define mem(a,x) memset(a,x,sizeof(a))
const int chr=26;
struct node
{
int nxt[chr];
node()
{
mem(nxt,-1);
}
};
node T[MX];
int suffix[MX],indx,len,path[MX];
int val[MX],ed[MX];
//int E[MX], esf[MX];
//vector<int>v[MX]; // list of index where an macth is ocurr for the i'th string
struct Aho_Corasick
{
void init()
{
//mem(esf,0); // contain immediate previous suffix which is an endpoint of a given string
//mem(E,0); // check if the vertex is a endpoint or not
len=indx=0;
mem(T,0);
mem(suffix,0);
mem(val,0);
T[indx]=node();
}
void insert(string s, int p)
{
int now=0;
for(int i=0; i<s.size(); i++)
{
int id=s[i]-'a';
if(T[now].nxt[id]==-1)
{
T[now].nxt[id]=++indx;
T[indx]=node();
}
now=T[now].nxt[id];
}
ed[p]=now;
//E[now]=p;
}
void reverse_link()
{
queue<int>q;
for(int i=0; i<chr; i++)
{
if(T[0].nxt[i]!=-1)
{
q.push(T[0].nxt[i]);
}
else T[0].nxt[i]=0;
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0; i<chr; i++)
{
int v=T[u].nxt[i];
if(v==-1)
{
T[u].nxt[i]=T[suffix[u]].nxt[i]; continue;
}
suffix[v]=T[suffix[u]].nxt[i];
q.push(v);
path[len++]=v;
//if(E[suffix[v]]) esf[v]=suffix[v];
//else esf[v]=esf[suffix[v]];
}
}
}
void search(string s)
{
int now=0;
for(int i=0; i<s.size(); i++)
{
int id=s[i]-'a';
now=T[now].nxt[id];
val[now]++;
//int nd=now;
//while(nd>0)
//{
// if(E[nd]) v[E[nd]].push_back(i+1);
// nd=esf[nd];
//}
}
for(int i=len-1; i>=0; i--)
{
val[suffix[path[i]]]+=val[path[i]];
}
}
}AC;
int main()
{
int tc,cs=1;
cin>>tc;
while(tc--)
{
AC.init();
int n; string T;
cin>>n>>T;
for(int i=1; i<=n; i++)
{
string s;
cin>>s;
AC.insert(s,i);
}
AC.reverse_link();
AC.search(T);
cout<<"Case "<<cs++<<":\n";
for(int i=1; i<=n; i++) cout<<val[ed[i]]<<'\n';
}
return 0;
}