给定几个模式串,看是否出现在主串中。
用所给的模式串构建AC自动机,然后用主串去匹配。
每个模式串的末尾记录该串的标号,而中间的字符的标号为0即可,最后跑一次AC自动机就行了。
3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
Sample Output
web 1: 1 2 3
total: 1
const int maxn = 1000008 ;
struct TrieNode{
TrieNode *fail ;
TrieNode *next[130] ;
int id ;
TrieNode(){
fail = NULL ;
id = 0 ;
for(int i = 0 ; i < 130 ; i++) next[i] = NULL ;
}
};
void Insert(TrieNode *root , char *s , int id){
TrieNode *now = root ;
while(*s){
int k = *s - ' ' ;
if(now->next[k] == NULL)
now->next[k] = new TrieNode() ;
now = now->next[k] ;
s++ ;
}
now->id = id ;
}
TrieNode *que[maxn] ;
void makeAC(TrieNode *root){
int head = 0 , tail = -1 ;
que[++tail] = root ;
while(head <= tail){
TrieNode *now = que[head++] ;
for(int i = 0 ; i < 130 ; i++){
if(now->next[i] != NULL){
if(now == root)
now->next[i]->fail = root ;
else{
TrieNode *f = now->fail ;
while(f != NULL){
if(f->next[i] != NULL){
now->next[i]->fail = f->next[i] ;
break ;
}
f = f->fail ;
}
if(f == NULL)
now->next[i]->fail = root ;
}
que[++tail] = now->next[i] ;
}
}
}
}
int vis[508] ;
int ask(TrieNode *root , char *s){
memset(vis , 0 , sizeof(vis)) ;
TrieNode *now = root ;
int sum = 0 , k ;
while(*s){
k = *s - ' ' ;
while(now != root && now->next[k] == NULL)
now = now->fail ;
now = now->next[k] ;
if(now == NULL) now = root ;
TrieNode *f = now ;
while(f != root){
vis[f->id] = 1 ;
if(f->id > 0) sum++ ;
f = f->fail ;
}
s++ ;
}
return sum ;
}
char word[208] ;
char text[10008] ;
int main(){
int n , m , i , j , total ;
while(cin>>n){
TrieNode *root = new TrieNode() ;
for(i = 1 ; i <= n ; i++){
scanf("%s" , word) ;
Insert(root , word , i) ;
}
total = 0 ;
makeAC(root) ;
cin>>m ;
for(i = 1 ; i <= m ; i++){
scanf("%s" , text) ;
if(ask(root , text) > 0){
total++ ;
printf("web %d:" , i) ;
for(j = 1 ; j <= n ; j++){
if(vis[j]) printf(" %d" , j) ;
}
puts("") ;
}
}
printf("total: %d\n" ,total) ;
}
return 0 ;
}
/*AC-------------*/
const int maxn = 500*208 ;
const int kind = 128 ;
int next[maxn][kind] ;
int fail[maxn] ;
int id[maxn] ;
struct AC{
int root , n ;
int newnode(){
id[n] = 0 ;
for(int i = 0 ; i < kind ; i++) next[n][i] = -1 ;
return n++ ;
}
void Init(){
n = 0 ;
root = newnode() ;
}
void Insert(char *s , int idx){
int now = root , k ;
while(*s){
k = *s - ' ' ;
if(next[now][k] == -1)
next[now][k] = newnode() ;
now = next[now][k] ;
s++ ;
}
id[now] = idx ;
}
void makeAc(){
queue<int> q ;
fail[root] = root ;
int now , i ;
for(i = 0 ; i < kind ; i++){
if(next[root][i] == -1)
next[root][i] = root ;
else{
fail[next[root][i]] = root ;
q.push(next[root][i]) ;
}
}
while(! q.empty()){
now = q.front() ; q.pop() ;
for(i = 0 ; i < kind ; 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]) ;
}
}
}
}
bool vis[508] ;
int ask(char *s , int m , int idx){
memset(vis , 0 , sizeof(vis)) ;
int now = root , k ;
while(*s){
k = *s - ' ' ;
now = next[now][k] ;
int t = now ;
while(t != root){
vis[id[t]] = 1 ;
t = fail[t] ;
}
s++ ;
}
vector<int> lis ; lis.clear() ;
for(int i = 1 ; i <= m ; i++){
if(vis[i]) lis.push_back(i) ;
}
if(lis.size() == 0) return 0 ;
else{
printf("web %d:" , idx) ;
for(int i = 0 ; i < lis.size() ; i++) printf(" %d" , lis[i]) ;
puts("") ;
return 1 ;
}
}
}ac ;
/*EndAc---------------*/
char word[208] ;
char text[10008] ;
int main(){
int t , n , i , sum , m ;
while(cin>>n){
ac.Init() ;
for(i = 1 ; i <= n ; i++){
scanf("%s" , word) ;
ac.Insert(word , i) ;
}
ac.makeAc() ;
sum = 0 ;
cin>>m ;
for(i = 1 ; i <= m ; i++){
scanf("%s" , text) ;
sum += ac.ask(text , n , i) ;
}
printf("total: %d\n" , sum) ;
}
return 0 ;
}