终于把ac自动机学完了 先刷一个水题吧...
开始无限re。。 众哥帮我调的
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define FF(i,a) for( int i = 0 ; i < a ; i ++ )
#define CC(m,what) memset(m,what,sizeof(m))
const int NODE = 600000;
const int CH = 26;
int chd[NODE][CH] , cnt;//结点个数
int word[NODE];//关键数组,记录每个单词尾结点的信息,每道题目都不一样
int fail[NODE];//传说中的失败指针
int Que[NODE];//辅助队列
int sw[150];//string swap每个字符对应的Index,方便模板化
void Ins(char *a, int val) {
int p = 0;
for(; *a ; a ++) {
int c = sw[*a];
if(!chd[p][c]) {
//CC(chd[cnt] , 0);
memset( chd[cnt], 0, sizeof( chd[cnt] ));
word[cnt] = 0;
chd[p][c] = cnt ++;
}
p = chd[p][c];
}
word[p] += val;
}
void AC() {
int *s = Que , *e = Que;
for ( int i = 0; i < CH; i++ )
if(chd[0][i]) {
fail[chd[0][i]] = 0;
*e++ = chd[0][i];
}
while(s != e) {
int p = *s++;
for ( int i = 0 ; i < CH; i ++ ) {
if( chd[p][i] ) {
int v = chd[p][i];
*e++ = v;
fail[v] = chd[fail[p]][i];
//word[v] += word[fail[v]];
//对word[v]按word[fail[v]]里的内容进行处理
} else {
chd[p][i] = chd[fail[p]][i];
}
}
}
}
void init ()
{
fail[0] = 0;
for( int i = 0; i < CH; i++ ) sw[i+'a'] = i;
//下面两句每次都必须初始化
//CC(chd[0],0);
memset( chd[0], 0,sizeof( chd[0] ));
cnt = 1;
}
//AC()函数处理后 chd[p][i] 就是在p结点进行i转移到达的结点
char c[1000050];
int main() {
int Case ;
//freopen ("out.txt" , "r" , stdin );
scanf("%d" , &Case );
while ( Case -- )
{
int n;
init();
scanf("%d" ,& n );
char str[100];
for ( int i = 0; i < n; i ++ )
{
scanf("%s" , str );
Ins( str, 1 );
}
AC();
int ans = 0;
scanf("%s" , c );
int now = 0;
char s ;
int len = strlen ( c ) ;
for ( int i = 0 ; i < len; i++ )
{
s = c[i];
//cout << s << endl;
now = chd[now][sw[s]];
//cout << now << endl;
ans += word[now];
word[now] = 0;
int p = now;
while ( p != 0 )
{
ans += word[p];
word[p] = 0;
p = fail[p];
}
//cout << ans << endl;
}
printf("%d\n" , ans );
}
return 0;
}