第一道AC自动机题目,这道题是模板题,唯一需要注意的是模式串可能会重复,所以需要累加。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 10000 * 50 + 100;
const int max_node = 1000000 + 10;
const int child_num = 26;
const int max_word = 50 + 10;
class ACAutumaton
{
private:
int chd[maxn][child_num];
int fail[maxn],val[maxn];
int Q[maxn];
int ID[128];
int sz;
public:
void Initialize()
{
fail[0] = 0;
for(int i = 0;i < child_num;i++)
{
ID[i + 'a'] = i;
}
}
void Reset()
{
memset(chd[0],0,sizeof(chd[0]));
sz = 1;
}
void Insert(char *a,int key)
{
int p = 0;
for(;*a ;a++)
{
int c = ID[*a];
if(!chd[p][c])
{
memset(chd[sz],0,sizeof(chd[sz]));
val[sz] = 0;
chd[p][c] = sz++;
}
p = chd[p][c];
}
val[p] += key;
}
void Construct()
{
int *s = Q,*e = Q;
for(int i = 0;i < child_num;i++)
{
if(chd[0][i])
{
fail[ chd[0][i] ] = 0;
*e ++ = chd[0][i];
}
}
while(s != e)
{
int u = *s++;
for(int i = 0;i < child_num;i++)
{
int &v = chd[u][i];
if(v)
{
*e ++ = v;
fail[v] = chd[ fail[u] ][i];
}
else v = chd[ fail[u] ][i];
}
}
}
int work(char *T)
{
int n = strlen(T);
int x = 0,ans = 0;
for(int i = 0;i < n;i++)
{
x = chd[x][ID[T[i]]];
int tmp = x;
while(tmp && val[tmp] != -1)
{
ans += val[tmp];
val[tmp] = -1;
tmp = fail[tmp];
}
}
return ans;
}
}AC;
int n,T;
char temp[max_word],exp[max_node];
void init()
{
freopen("hdu2222.in","r",stdin);
freopen("hdu2222.out","w",stdout);
}
void readdata()
{
AC.Initialize();
scanf("%d",&T);
while(T--)
{
AC.Reset();
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%s",temp);
AC.Insert(temp,1);
}
AC.Construct();
scanf("%s",exp);
printf("%d\n",AC.work(exp));
}
}
int main()
{
init();
readdata();
return 0;
}