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;
    } 
    

      

  • 相关阅读:
    EntityFramework 启用迁移 EnableMigrations 报异常 "No context type was found in the assembly"
    JAVA 访问FTP服务器示例(2)
    NuGet Package Manager 更新错误解决办法
    JAVA 访问FTP服务器示例(1)
    RemoteAttribute 的使用问题
    诡异的 javascript 变量
    javascript apply用法
    Babun 中文乱码
    GSM呼叫过程
    转站博客园
  • 原文地址:https://www.cnblogs.com/guangheli/p/9897755.html
Copyright © 2011-2022 走看看