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 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;
}
posted on 2011-11-20 17:56  追逐.  阅读(166)  评论(0编辑  收藏  举报