hdu 2222:
#include<cstdio>
#include<cstring>
#define mm 88888
#define mn 55
#define N 26
int tire[mm][N];
int fail[mm],w[mm],Q[mm];
int cg[128];
int size;
char tmp[mn],s[1111111];
void build(char *word){
int i=0,j;
for(;*word;++word,i=tire[i][j])
if(!tire[i][j=cg[*word]]){
memset(tire[size],0,sizeof(tire[size]));
w[tire[i][j]=size++]=0;
}
++w[i];
}
void AC(){
int *l=Q,*r=Q,i,j,k;
for(i=0;i<N;++i)
if(tire[0][i])fail[*r++=tire[0][i]]=0;
for(;l!=r;++l)
for(i=*l,j=0;j<N;++j)
if(k=tire[i][j])fail[*r++=k]=tire[fail[i]][j];
else tire[i][j]=tire[fail[i]][j];
}
int main(){
int i,j,r,n,T,ans;
for(fail[0]=i=0; i<26; ++i)cg[i+'a']=i;
scanf("%d",&T);
while(T--){
memset(tire[0],0,sizeof(tire[0]));
size=1;
scanf("%d",&n),getchar();//getchar()接收换行符
while(n--)gets(tmp),build(tmp);
AC();
gets(s);
ans=i=r=0;
while(s[r]){
j=i=tire[i][cg[s[r++]]];
while(j&&w[j]!=-1)
ans+=w[j],w[j]=-1,j=fail[j];
}
printf("%d\n",ans);
}
return 0;
#include<cstring>
#define mm 88888
#define mn 55
#define N 26
int tire[mm][N];
int fail[mm],w[mm],Q[mm];
int cg[128];
int size;
char tmp[mn],s[1111111];
void build(char *word){
int i=0,j;
for(;*word;++word,i=tire[i][j])
if(!tire[i][j=cg[*word]]){
memset(tire[size],0,sizeof(tire[size]));
w[tire[i][j]=size++]=0;
}
++w[i];
}
void AC(){
int *l=Q,*r=Q,i,j,k;
for(i=0;i<N;++i)
if(tire[0][i])fail[*r++=tire[0][i]]=0;
for(;l!=r;++l)
for(i=*l,j=0;j<N;++j)
if(k=tire[i][j])fail[*r++=k]=tire[fail[i]][j];
else tire[i][j]=tire[fail[i]][j];
}
int main(){
int i,j,r,n,T,ans;
for(fail[0]=i=0; i<26; ++i)cg[i+'a']=i;
scanf("%d",&T);
while(T--){
memset(tire[0],0,sizeof(tire[0]));
size=1;
scanf("%d",&n),getchar();//getchar()接收换行符
while(n--)gets(tmp),build(tmp);
AC();
gets(s);
ans=i=r=0;
while(s[r]){
j=i=tire[i][cg[s[r++]]];
while(j&&w[j]!=-1)
ans+=w[j],w[j]=-1,j=fail[j];
}
printf("%d\n",ans);
}
return 0;
}
通用模版:
#include<cstring>
#define FF(i,a) for( int i = 0 ; i < a ; i ++ )
#define CC(m,what) memset(m,what,sizeof(m))
const int NODE = 1500;
const int CH = 4;
int chd[NODE][CH] , sz;//结点个数
int word[NODE];//关键数组,记录每个单词尾结点的信息,每道题目都不一样
int fail[NODE];//传说中的失败指针
int Que[NODE];//辅助队列
int sw[128];//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[sz] , 0);
word[sz] = 0;
chd[p][c] = sz ++;
}
p = chd[p][c];
}
word[p] = val;
}
void AC() {
int *s = Que , *e = Que;
FF(i,CH) if(chd[0][i]) {
fail[ chd[0][i] ] = 0;
*e++ = chd[0][i];
}
while(s != e) {
int p = *s++;
FF(i,CH) {
if(chd[p][i]) {
int v = chd[p][i];
*e++ = v;
fail[v] = chd[fail[p]][i];
//对word[v]按word[fail[v]]里的内容进行处理
} else {
chd[p][i] = chd[fail[p]][i];
}
}
}
}
//AC()函数处理后 chd[p][i] 就是在p结点进行i转移到达的结点
int main() {
fail[0] = 0;
FF(i,26) sw[i+'a'] = i;
//下面两句每次都必须初始化
CC(chd[0],0);
sz = 1;
}
#define CC(m,what) memset(m,what,sizeof(m))
const int NODE = 1500;
const int CH = 4;
int chd[NODE][CH] , sz;//结点个数
int word[NODE];//关键数组,记录每个单词尾结点的信息,每道题目都不一样
int fail[NODE];//传说中的失败指针
int Que[NODE];//辅助队列
int sw[128];//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[sz] , 0);
word[sz] = 0;
chd[p][c] = sz ++;
}
p = chd[p][c];
}
word[p] = val;
}
void AC() {
int *s = Que , *e = Que;
FF(i,CH) if(chd[0][i]) {
fail[ chd[0][i] ] = 0;
*e++ = chd[0][i];
}
while(s != e) {
int p = *s++;
FF(i,CH) {
if(chd[p][i]) {
int v = chd[p][i];
*e++ = v;
fail[v] = chd[fail[p]][i];
//对word[v]按word[fail[v]]里的内容进行处理
} else {
chd[p][i] = chd[fail[p]][i];
}
}
}
}
//AC()函数处理后 chd[p][i] 就是在p结点进行i转移到达的结点
int main() {
fail[0] = 0;
FF(i,26) sw[i+'a'] = i;
//下面两句每次都必须初始化
CC(chd[0],0);
sz = 1;
}