第一道自己A掉的AC自动机的题目,舒服~~
AC自动机的题目,要注意要按照输入的字符串顺序输出,我是用vector存,然后两个map
mp 表示节点k 为终点的 字符串
mp2 表示 字符串 s 出现的个数
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <vector>
#include <string>
using namespace std;
const int N = 5e4 + 10;
const int M = 2e6 + 10;
const int rg = 30;
vector<string> vct;
map<int,string> mp;
map<string,int> mp2;
int n,ch[N][rg],last[N],f[N],sz,root;
char s[M];
int newnode(){
memset(ch[sz],-1,sizeof(ch[sz]));
last[sz++] = 0;
return sz -1 ;
}
void init(){
sz = 0;
root = newnode();
}
void insert(char * s){
int len = strlen(s);
int now = root;
for(int i = 0;i<len;i++){
if(ch[now][s[i]-'A'] == -1 ) ch[now][s[i]-'A'] = newnode();
now = ch[now][s[i] - 'A'];
}
last[now] = 1;
mp[now] = s;
}
void build(){
queue<int> Q;
for(int i = 0;i<rg;i++){
if(ch[root][i] == -1) ch[root][i] = root;
else {
f[ch[root][i]] = root;
Q.push(ch[root][i]);
}
}
while(!Q.empty()){
int now = Q.front();
Q.pop();
for(int i = 0;i<rg;i++){
if(ch[now][i] == -1) ch[now][i] = ch[f[now]][i];
else {
f[ch[now][i]] = ch[f[now]][i];
Q.push(ch[now][i]);
}
}
}
}
void query(char * s){
int len = strlen(s);
int now = root;
for(int i = 0;i<len;i++){
if(!(s[i] >= 'A' && s[i] <= 'Z')) now = root;
else {
now = ch[now][s[i]-'A'];
int tmp = now;
while(tmp != root){
if(last[tmp]) mp2[mp[tmp]]++;
tmp = f[tmp];
}
}
}
for(auto u : vct){
if(mp2[u])
printf("%s: %d\n",u.c_str(),mp2[u]);
}
}
void debug(){
for(int i = 0;i<sz;i++){
printf("id = %3d , fail = %3d,end = %3d chi = [",i,f[i],last[i]);
for(int j =0; j<rg;j++)
printf("%2d",ch[i][j]);
printf("]\n");
}
}
int main(){
while(~scanf("%d",&n)) {
mp.clear();mp2.clear();
vct.clear()
init();
for(int i = 0;i<n;i++){
scanf("%s",s);
insert(s);
vct.push_back(s);
}
//debug();
build();
scanf("%s",s);
query(s);
}
return 0;
}