标签:
题目链接:点击打开链接
题目大意:给出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