-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaho.cpp
139 lines (131 loc) · 3.15 KB
/
aho.cpp
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
#include <cstdio>
#include <cstring>
#include <queue>
#define MAX_CHAR_NUM 500006
#define MAX_STRING_LEN 100006
/*
* the aho use the double array to build the machine
*/
struct Aho{
struct state{
int next[26];//if there is only a-z. also can expend to the 256 ascii
//cnt how many string finish in this state
int fail,cnt;//this table's fail point to the next statetable.
}statetable[MAX_CHAR_NUM];//how many chars are there
int size;//count of the ac nodes
std::queue<int> que;
int init(){
while(que.size()){
que.pop();
}
size = 1; //has one root node
for(int i=0;i<MAX_CHAR_NUM;++i){
memset(statetable[i].next,0,sizeof(statetable[i].next));
statetable[i].fail = 0;
statetable[i].cnt = 0;
}
}
//insert the mode string s
int insert(char *S){
int now = 0;
int len = strlen(S);
for(int i=0;i<len;++i){
char c = S[i];
if(!statetable[now].next[c-'a']){
statetable[now].next[c-'a'] = size++;
}
now = statetable[now].next[c-'a'];
}
statetable[now].cnt++;
}
//build the failed point
//each node has one char
//the fail pointer only point to the statetable items
int build() {
statetable[0].fail = -1;
que.push(0);
while(que.size()){
//the u is the index of which statetable
int u = que.front();
que.pop();
for(int i = 0;i<26;i++){
if(statetable[u].next[i]){
if(0 == u) statetable[statetable[u].next[i]].fail = 0;
else{
int v = statetable[u].fail;
//look for the father or ff or fff ... pointer item whether has the next[i]
while(-1 != v){
if(statetable[v].next[i]){
//has the next[i]
statetable[statetable[u].next[i]].fail = statetable[v].next[i];
break;
}
v = statetable[v].fail;
}
if(-1 == v){
statetable[statetable[u].next[i]].fail = 0;
}
}
//push the next[i] into the que
que.push(statetable[u].next[i]);
}//end of if
}
}//finish the build fail point
return 0;
}
//get the index of statetable item from the now to the root
//get the cnt sum of each node
int Get(int now){
int res = 0;
while(now){
res += statetable[now].cnt;
statetable[now].cnt = 0;
now = statetable[now].fail;
}
return res;
}
//the main string S
int match(char *S){
int len = strlen(S);
int now = 0;
int res = 0; //return the how many keyword are there in machine
//if there are two same keyword only count once so need to set zero after the count
for(int i = 0;i < len;i++){
char c = S[i];
if(statetable[now].next[c-'a']){
now = statetable[now].next[c-'a'];
}else{
int p = statetable[now].fail;
while(p != -1 && statetable[p].next[c-'a'] == 0) p = statetable[p].fail;
if(-1 == p) now = 0;
else{
now = statetable[p].next[c-'a'] ;
}
}
if(statetable[now].cnt){
res = res + Get(now);
}
}
return res;
}
}aho;
int T;//times
int N;//how many mode strings
char str[MAX_STRING_LEN];
int main(){
int ret;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
aho.init();
for(int i=0;i<N;i++){
scanf("%s",str);
aho.insert(str);
}
aho.build();
scanf("%s",str);
ret = aho.match(str);
printf("%d\n",ret);
}
return 0;
}