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

    题目描述:

    小张最近在忙毕设,所以一直在读论文。

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

    题解:

    AC 自动机裸题,将所有字符串读入到一个数组里,字符串之间用 “#” 隔开即可。

    Code:

    #include<string>
    #include<vector>
    #include<queue>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    void setIO(string a){
    	freopen((a+".in").c_str(),"r",stdin);
    }
    
    #define maxn 2000004
    vector<int>G[maxn];
    char arr[maxn],total[maxn];
    int tag[maxn],ans[maxn],map[maxn],cnt=-1;
    struct Automaton{
    	#define idx str[i]-'a' 
    	#define root 0
    	#define sigma 27
    	int ch[maxn][sigma],last[maxn],fail[maxn],end[maxn];
    	int nodes;
    	int newnode(){ return ++nodes;}
    
    	void insert(char str[],int id){
    	    int n=strlen(str);
    	    int pos=root;
    	    for(int i=0;i<n;++i){
    	    	if(!ch[pos][idx]) ch[pos][idx]=newnode();
    	    	pos=ch[pos][idx];
    	    }
    	    G[pos].push_back(id);
    	    end[pos]=1;
    	    map[id]=pos;
        }
    
        queue<int>Q;
        void build(){
        	for(int i=0;i<sigma;++i) if(ch[root][i]) { Q.push(ch[root][i]),fail[ch[root][i]]=root; }
        	while(!Q.empty()){
        		int u=Q.front(); Q.pop();
        		for(int i=0;i<sigma;++i){
        			int r=ch[u][i];
        			if(!r) { ch[u][i]=ch[fail[u]][i]; continue; }
        			Q.push(r);
        			fail[r]=ch[fail[u]][i];
        			last[r]=end[fail[r]]? fail[r]: last[fail[r]];
        		}
        	}
        }
    
        bool vis[maxn];
        void print(int j){
        	while(j){
        		if(end[j]) tag[j]+=1;
        		j=last[j];
        	}
        }
    
        void query(char str[]){
        	int j=root;
        	for(int i=0;i<cnt;++i){
        		if(str[i]=='#') j=root;
        		else
        		{
        			j=ch[j][idx];
        			print(j);
        		}
        	}
        }   
    
    }aho;
    int main(){
    	//setIO("input");
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)  {
    		scanf("%s",arr), aho.insert(arr,i);
    		int cur_n=strlen(arr);
    		for(int j=0;j<cur_n;++j)
    			total[++cnt]=arr[j];
    		total[++cnt]='#';
    		++cnt;
    	}
    	aho.build();
        aho.query(total);
        for(int i=0;i<maxn;++i)
        	for(int j=0;j<G[i].size();++j) ans[G[i][j]]+=tag[i];
        for(int i=1;i<=n;++i) printf("%d
    ",ans[i]);
        return 0;
    } 
    

      

  • 相关阅读:
    红线行动开发文档
    团队作业1
    第二次作业:安装VS2015和使用自动测试管理工具
    简单介绍VS2015自动测试工具
    软件工程作业(一)
    三带一队 实验十 团队作业6:团队项目用户验收&BETA冲刺
    《三带一队》【Beta】Scrum meeting 4
    《三带一队》【Beta】Scrum meeting 3
    《三带一队》【Beta】Scrum meeting 2
    《三带一队》【Beta】Scrum meeting 1
  • 原文地址:https://www.cnblogs.com/guangheli/p/9897755.html
Copyright © 2011-2022 走看看