hdu 3065 AC自动机 标记数组不清零

题目链接:

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

题目里面要我们计算每种单词出现的次数,重叠的也要计算,那么我们在查找的时候不要把标记单词结尾的数组(我这里是val)清零就可以重复计算每个单词出现的数量了。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque> 
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 50005
int trie[maxn][95],fail[maxn],val[maxn],ID[maxn],num[maxn];
int n,m,k,t,cnt;
char s[1005][55],str[2000005];
void init(){
    memset(trie,0,sizeof(trie));
    memset(fail,0,sizeof(fail));
    memset(val,0,sizeof(val));
    memset(num,0,sizeof(num));
    cnt=0;
}
void insert(char *s,int id){
    int root=0;
    for(int i=0;s[i];i++){
        int x=s[i]-32;
        if(trie[root][x]==0)
        trie[root][x]=++cnt;
        root=trie[root][x];
    }
    val[root]++;
    ID[root]=id;//记录编号 
}
void build_fail(){//构建fail指针 
    queue<int>q;
    int root=0;
    for(int i=0;i<95;i++){
        if(trie[root][i])
        q.push(trie[root][i]);
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=0;i<95;i++){
            if(trie[u][i]){//u存在儿子i,把i的fail指向fail[u]的儿子i 
                fail[trie[u][i]]=trie[fail[u]][i];
                q.push(trie[u][i]);
            }else{//不存在儿子i 
                trie[u][i]=trie[fail[u]][i];//让fail[u]的儿子i成为u的儿子 
            }
        }
    }
}
void query(){
    int len=strlen(str);
    int u=0;
    for(int i=0;i<len;i++){
        int id=str[i]-32;
        u=trie[u][id];
        int temp=u;
        while(temp){
            if(val[temp]){//找到一个以id+32这个字符结束的单词,我们在这里不把它的标记数组val清零 
                num[ID[temp]]++;
            }
            temp=fail[temp];
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF){
        init();
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]);
            insert(s[i],i); 
        }
        build_fail();
        scanf("%s",str);
        query();
        for(int i=1;i<=n;i++){
            if(num[i]){
                printf("%s: ",s[i]);
                printf("%d\n",num[i]);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/6262369sss/p/10301152.html