标签:
题目链接:点击打开链接
题目大意:给出n个字符串主串,和m个模式串,定义f(A,B)为B串在A串中出现的次数,现在对每一个A串都计算
∑f(Ai,Bj) (1 <= j <= m),并输出。
对m个模式串建立AC自动机,然后每个主串都放入自动机中,统计主串包含多少B内的串,并输出。
注意:
标记的时候直接累加值,可能会有多个模式串相同。
统计的时候,使用fail一直要回到根。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std ;
#define LL __int64
#pragma comment(linker, "/STACK:102400000,102400000")
struct node
{
int data ;
node *next[26] , *fail ;
};
string str[10010] , s ;
LL sum ;
queue <node*> que ;
node *newnode()
{
node *p = new node ;
p->data = 0 ;
p->fail = NULL ;
for( int i = 0 ; i < 26 ; i++)
p->next[i] = NULL ;
return p ;
}
void settree(node *rt)
{
int i , k , l = s.size() ;
node *p = rt ;
for(i = 0 ; i < l ; i++)
{
k = s[i] - 'a' ;
if( p->next[k] == NULL )
p->next[k] = newnode() ;
p = p->next[k] ;
}
p->data++ ;
}
void setfail(node *rt)
{
int i ;
node *p , *temp ;
while( !que.empty() ) que.pop() ;
que.push(rt) ;
while( !que.empty() )
{
p = que.front() ;
que.pop() ;
for(i = 0 ; i < 26 ; i++)
{
if( p->next[i] )
{
temp = p->fail ;
while( temp && !temp->next[i] )
temp = temp->fail ;
p->next[i]->fail = temp ? temp->next[i] : rt ;
que.push(p->next[i]) ;
}
else
p->next[i] = p == rt ? rt : p->fail->next[i] ;
}
}
return ;
}
void query(int u,node *rt)
{
int i , k , l = str[u].size() ;
node *p = rt , *temp ;
for(i = 0 ; i < l ; i++)
{
if( str[u][i] < 'a' || str[u][i] > 'z' )
{
p = rt ;
continue ;
}
k = str[u][i] - 'a' ;
p = p->next[k] ;
for( temp = p ; temp ; temp = temp->fail ) {
sum += temp->data ;
}
}
return ;
}
int main()
{
int n , m , i , t ;
node *rt ;
scanf("%d", &t) ;
while( t-- ) {
rt = newnode() ;
scanf("%d %d", &n, &m) ;
for(i = 0 ; i < n ; i++)
cin >> str[i] ;
for(i = 0 ; i < m ; i++) {
cin >> s ;
settree(rt) ;
}
setfail(rt) ;
for(i = 0 ; i < n ; i++) {
sum = 0 ;
query(i,rt) ;
printf("%I64d\n", sum) ;
}
}
return 0;
}版权声明:转载请注明出处:http://blog.csdn.net/winddreams
hdu5384(2015多校8)--Danganronpa(AC自动机)
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/47620709