zoukankan      html  css  js  c++  java
  • [BZOJ3172 ][Tjoi2013]单词(AC自动机)

    Description

    不稳定的传送门

    某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
    单词个数<=200,单词总长度<=10^6

    Solution

    AC自动机的入门题,将所有单词建一颗字典树,并构造fail树

    然后随便统计一下数量就可以了

    Code

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define R register
    #define N 1000002
    using namespace std;
    
    char s[N];
    int n,T[N][27],fail[N],e[N][2],head[N],q[N],tot,h,t,num=1,wr[201];
    
    inline void Insert(int k){
    	int len=strlen(s);
    	for(R int now=1,i=0;i<len;++i){
    		if(T[now][s[i]-96]==0) T[now][s[i]-96]=++num;
    		now=T[now][s[i]-96];
    		T[now][0]++;
    		if(i==len-1) wr[k]=now;
    	}
    }
    
    inline void Link(int u,int v){
    	e[++tot][0]=v,e[tot][1]=head[u],head[u]=tot; 
    }
    
    inline void getfail(){
    	int k,now;
    	h=0,t=1;q[1]=1;
    	while(h<t){
    		now=q[++h];
    		for(R int i=1;i<=26;++i)
    			if(T[now][i]!=0){
    				k=fail[now];
    				while(k!=0&&T[k][i]==0) k=fail[k];
    				if(T[k][i]!=0) fail[T[now][i]]=T[k][i];
    				else fail[T[now][i]]=1;
    				Link(fail[T[now][i]],T[now][i]);
    				q[++t]=T[now][i];
    			}
    	}
    }
    
    inline int calc(int k){
    	for(R int j=head[k];j;j=e[j][1]){
    		T[k][0]+=calc(e[j][0]);
    	}
    	return T[k][0];
    }
    
    int main(){
    	scanf("%d",&n);
    	T[1][0]=1;
    	for(R int i=1;i<=n;++i){
    		scanf("%s",s);
    		Insert(i);
    	}
    	getfail();
    	calc(1);
    	for(R int i=1;i<=n;++i) printf("%d
    ",T[wr[i]][0]);
    	return 0;
    }
    

    Solution

  • 相关阅读:
    孔曰成仁,孟曰取义
    mysql索引&实现原理
    MySQL存储引擎
    HashMap原理
    反射
    list对象属性排序
    mysql数据表操作&库操作
    mysql字段类型
    java线程池初步理解
    java四种内部类
  • 原文地址:https://www.cnblogs.com/void-f/p/8901847.html
Copyright © 2011-2022 走看看