按序输出,不重复:
#include <bits/stdc++.h>
using namespace std;
const char base = '0';
const int maxkind = 10;
const int maxchar = 60005;
const int maxword = 10002;
char target[maxchar];
char words[maxword][62];
int trie[600002][maxkind];
int fail[600002];
int isword[600002];
int color[600002];
queue<int> q;
queue<int> res;
int cnt = 1;
int m,n;
void ACtrie(){
int p,l,c;
for(int i=1;i<=n;i++){
l = strlen(words[i]);
p = 0;
for(int j=0;j<l;j++){
c = words[i][j] - base;
if(trie[p][c] !=0 ) p = trie[p][c];
else p = trie[p][c] = cnt++;
}
isword[p] = i;
}
}
void ACfail(){
while(!q.empty()) q.pop();
q.push(0);
int p ;
while(!q.empty()){
p = q.front();
q.pop();
int fp = fail[p];
for(int i=0;i<maxkind;i++){
if(trie[p][i] != 0) q.push(trie[p][i]);
if(trie[p][i] != 0 && trie[fp][i] !=0 && p!=fp){
fail[trie[p][i]] = trie[fp][i];
}
if(trie[p][i] == 0){
trie[p][i] = trie[fp][i];
}
}
}
}
void ACfind(){
while(!res.empty()) res.pop();
int l = strlen(target);
int p = 0;
for(int i=0;i<l;i++){
int c = target[i] - base;
p = trie[p][c];
int t = p;
while(color[t] == 0&&t!=0){
color[t] = 1;
if(isword[t] != 0) res.push(isword[t]);
t = fail[t];
}
}
}
void print(){
printf("Found key:");
while(!res.empty()){
printf(" [Key No. %d]",res.front());
res.pop();
}
printf("\n");
}
int main(){
freopen("input.txt","r",stdin);
memset(target,0,sizeof(target));
memset(words,0,sizeof(words));
memset(trie,0,sizeof(trie));
memset(fail,0,sizeof(fail));
memset(isword,0,sizeof(isword));
memset(color,0,sizeof(color));
scanf("%d%d",&m,&n);
while(m--){
char t[65];
scanf("%s",t);
sprintf(target,"%s%s",target,t);
}
for(int i=1;i<=n;i++){
char c;
while((c = getchar()) !=']');
scanf("%s",words[i]);
}
ACtrie();
ACfail();
ACfind();
print();
return 0;
}