HDU 2222 Keywords Search(AC自动机)

来源:互联网 发布:淘宝补差价链接买东西 编辑:程序博客网 时间:2024/06/08 05:37

HDU 2222 Keywords Search(AC自动机)

http://acm.hdu.edu.cn/showproblem.php?pid=2222

题意:

        给你多个模板组成的字典和一个文本,问你文本中出现了多少个模板。

分析:

        用模板建立AC自动机,然后初始化一个bool vis[]数组,用于标记每个模板,然后用文本串匹配AC自动机,每当扫描到一个单词节点就令vis[]=true.最后在在外面扫描一遍vis数组即可.(该题应该没有重复模板,根据题意)

        注意:经过测试该题有重复的模板,且如果模板已经出现过多次,只算一次.但是重复的模板要作为新模板同样计数.

AC代码:

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>using namespace std;const int maxnode=500000+100;const int sigma_size=26;int ans;struct AC_Automata{    int ch[maxnode][sigma_size];    int val[maxnode];//用于保存当前单词输入了几遍,当用find扫描文本的时候,只要遇到该单词就+val[i]且让vis[i]=false,使得下次遇到该模板不会重复计算    int f[maxnode];    int last[maxnode];    bool vis[maxnode];//非单词节点vis=0,单词节点vis=1.如果用find找到了单词i节点,那么vis=0.    int sz;    void init()    {        sz=1;        memset(ch[0],0,sizeof(ch[0]));        vis[0]=false;        last[0]=f[0]=val[0]=0;    }    void insert(char *s)    {        int n=strlen(s),u=0;        for(int i=0;i<n;i++)        {            int id=s[i]-'a';            if(ch[u][id]==0)            {                vis[sz]=false;                ch[u][id]=sz;                memset(ch[sz],0,sizeof(ch[sz]));                val[sz++]=0;            }            u=ch[u][id];        }        vis[u]=true;        val[u]++;    }    void print(int i)    {        if(val[i])        {            if(vis[i])            {                ans+=val[i];                vis[i]=false;            }            print(last[i]);        }    }    void find(char *s)    {        int n=strlen(s),j=0;        for(int i=0;i<n;i++)        {            int id=s[i]-'a';            while(j && ch[j][id]==0) j=f[j];            j=ch[j][id];            if(val[j]) print(j);            else if(last[j]) print(last[j]);        }    }    void getFail()    {        queue<int> q;        f[0]=0;        for(int i=0;i<sigma_size;i++)        {            int u=ch[0][i];            if(u)            {                last[u]=f[u]=0;                q.push(u);            }        }        while(!q.empty())        {            int r=q.front();q.pop();            for(int i=0;i<sigma_size;i++)            {                int u=ch[r][i];                if(!u) continue;                q.push(u);                int v=f[r];                while(v && ch[v][i]==0) v=f[v];                f[u]=ch[v][i];                last[u] = val[f[u]]?f[u]:last[f[u]];            }        }    }};AC_Automata ac;const int MAXN=1000000+100;char text[MAXN],word[100];int main(){    int T;    scanf("%d",&T);    while(T--)    {        ans=0;        ac.init();        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%s",word);            ac.insert(word);        }        ac.getFail();        scanf("%s",text);        ac.find(text);        printf("%d\n",ans);    }    return 0;}

0 0