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

      

  • 相关阅读:
    最大值和最小值
    GetLevelDesc函数
    21. D3DSprite
    SetFileAttributes和GetFileAttributes
    24. 幕外渲染
    D3D修改view矩阵与修改world矩阵的区别
    23. 保存纹理(保存屏幕截图)
    C++之solmyr小品文
    C++二进制文件写操作
    22. 凸凹贴图
  • 原文地址:https://www.cnblogs.com/guangheli/p/9897755.html
Copyright © 2011-2022 走看看