标签:
1 5 she he say shr her yasherhs
3
#include <cstdio>
#include <cstring>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=1000010;
const int bsz=26;
typedef long long ll;
char txt[1000010];
bool vis[510];
int ans;
struct Trie
{
    int ch[maxn][bsz],val[maxn],sz,cnt[maxn];  // ch存Trie val-节点对应的单词 cnt-节点结尾单词个数
    int f[maxn],last[maxn];//f-失配指针 last-后缀链接
    int newnode()
    {
        val[sz]=0; cnt[sz]=0;
        memset(ch[sz],-1,sizeof ch[sz]);
        return sz++;
    }
    void init()
    {
        sz=0;
        newnode();
    }
    int idx(char c)  // 取c的标号 具体看字符为什么
    {
        return c-'a';
    }
    void Insert(char *st,int id)
    {
        int u=0,n=strlen(st),c,i;
        for(i=0;i<n;i++)
        {
            c=idx(st[i]);
            if(ch[u][c]==-1)
                ch[u][c]=newnode();
            u=ch[u][c];
        }
        val[u]=id;
        cnt[u]++;
    }
    void build()
    {
        int u=0,v,i;
        queue<int> q;
        f[0]=0;
        for(i=0;i<bsz;i++)
        {
            v=ch[u][i];
            if(v==-1) ch[u][i]=0;
            else
            {
                f[v]=0;
                q.push(v);
            }
        }
        while(!q.empty())
        {
            u=q.front();
            q.pop();
            last[u]=val[f[u]]?f[u]:last[f[u]];
            for(i=0;i<bsz;i++)
            {
                v=ch[u][i];
                if(v==-1) ch[u][i]=ch[f[u]][i]; // 将NULL变为有意义 沿着父亲失配指针走第一个有意义的节点
                else
                {
                    f[v]=ch[f[u]][i];
                    q.push(v);
                }
            }
        }
    }
    bool Find(char *st,int m,int id)
    {
        int n=strlen(st),i,u=0,c,p,flag=0;
        //memset(vis,0,sizeof vis);  可标记哪些单词出现过 同样的单词只标记一个
        for(i=0;i<n;i++)
        {
            c=idx(st[i]);
            u=ch[u][c];
            p=val[u]?u:last[u];
            while(p)
            {
                //vis[val[p]]=true;
                if(val[p]){ ans+=cnt[p]; cnt[p]=0; }  // 加上该串出现次数  清零 避免重复计数
                flag=1;
                p=last[p];
            }
        }
        if(!flag) return false;
//        for(i=1;i<=m;i++)
//            if(vis[i])
//                printf(" %d",i);
//        putchar('\n');
        return true;
    }
} ac;
int main()
{
    int i,n,m,tot;
    scanf("%d",&tot);
    while(tot--)
    {
        scanf("%d",&n);
        ac.init();
        for(i=1;i<=n;i++)
        {
            scanf("%s",txt);
            ac.Insert(txt,i);
        }
        ac.build();
        ans=0;
        scanf("%s",txt);
        ac.Find(txt,n,i);
        printf("%d\n",ans);
    }
    return 0;
}
/*
1
5
she
he
say
her
her
yasherhs
*/
hdu 2222 Keywords Search(AC自动机入门)
标签:
原文地址:http://blog.csdn.net/tobewhatyouwanttobe/article/details/46405065