zoukankan      html  css  js  c++  java
  • [bzoj3172][Tjoi2013]单词——AC自动机

    题目大意:

    某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

    思路:

    第i个单词在整个文章中出现了多少次即i串的结尾可以被多少个串的节点给跳到。
    于是吧fail看成每个节点唯一的父亲,每个节点的权值为有多少个单词的前缀经过了它,然后直接统计子树内的权值和即可。

    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define debug(x) cout<<#x<<"="<<x<<" "
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
    	freopen("bzoj3172.in","r",stdin);
    	freopen("bzoj3172.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
    	_=0; T f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    	for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
    	_*=f;
    }
    
    const int maxn=1e6+10;
    int n,cnt_rank,ans[maxn],weight[maxn];
    int ch[maxn][26],num[maxn],fail[maxn],cnt=1;
    vector<int>rank[maxn];
    
    void insert(char *s){
    	int len=strlen(s+1),u=1,c;
    	REP(i,1,len){
    		c=s[i]-'a';
    		if(!ch[u][c])ch[u][c]=++cnt;
    		u=ch[u][c];
    		++weight[u];
    	}
    	++num[u];
    	rank[u].pb(++cnt_rank);
    }
    
    void build_fail(){
    	int h=1,t=0,q[maxn];
    	fail[1]=1;
    	REP(i,0,25){
    		int v=ch[1][i];
    		if(v)q[++t]=v;
    		if(v)fail[v]=1;
    		else ch[1][i]=1;
    	}
    	while(h<=t){
    		int u=q[h++];
    		REP(i,0,25){
    			int v=ch[u][i];
    			if(v)q[++t]=v;
    			if(v)fail[v]=max(ch[fail[u]][i],1);
    			else ch[u][i]=max(ch[fail[u]][i],1);
    		}
    	}
    }
    
    int beg[maxn],to[maxn],las[maxn],cnte=1;
    int sz[maxn];
    
    void add(int u,int v){
    	las[++cnte]=beg[u]; beg[u]=cnte; to[cnte]=v;
    }
    
    void dfs(int u){
    	sz[u]=weight[u];
    	for(int i=beg[u];i;i=las[i]){
    		dfs(to[i]);
    		sz[u]+=sz[to[i]];
    	}
    	REP(i,0,rank[u].size()-1)ans[rank[u][i]]=sz[u];
    }
    
    int main(){
    	File();
    
    	char s[maxn];
    
    	read(n);
    	REP(i,1,n){
    		scanf("%s",s+1);
    		//printf("%s
    ",s+1);
    		insert(s);
    	}
    
    	build_fail();
    	REP(i,2,cnt)add(fail[i],i);
    
    	dfs(1);
    
    	REP(i,1,n)printf("%d
    ",ans[i]);
    
    	return 0;
    }
    
    
  • 相关阅读:
    eclipse使用maven时 java.lang.ClassNotFoundException: org.springframework.web.util.IntrospectorCleanupListener
    js闭包泄漏-replaceThing问题(A surprising JavaScript memory leak found at Meteor)
    lua package path 设置方法
    Linux 网络相关命令
    is not in the sudoers file 解决(转)
    MySQL中的datetime与timestamp比较
    select random item with weight 根据权重随机选出
    [linux] 系统管理常用命令
    [python] 字符串与列表、字典的转换
    [python]pep8编码规范
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10185297.html
Copyright © 2011-2022 走看看