• UVA 11019 Matrix Matcher


    解析:给定一个矩阵,求另一矩阵在这个矩阵中出现的次数;

    假设N*M矩阵为T,X*Y矩阵为P
    方法是利用count[i][j]来记录以(i,j)为左上角,且大小为X,Y的矩形中含有多少个完整行与P矩阵对应行完全相同
    所以,如果在T矩阵的第r行的第c列开始与P的第i行匹配,那么count[r-i][c]++;
    最后判断是否有count[][]==X;

    PS:这题是AC自动机的进阶题目,可以参考HDU 2222,是这题的一维简化版

    #include"stdio.h"
    #include"string.h"
    #include"stdlib.h"
    #include"queue"
    using namespace std;
    #define maxnode (100*100+10)
    #define sigma_size 26
    
    int N,M,X,Y;
    char map[1005][1005];
    int cnt[1005][1005];
    
    struct AC_automation{			
    	struct node{
    		int next[sigma_size];
    		int val;	//树节点的附加信息
    		int fail;	//存储节点的失配指针
    		vector<int>line;	//记录该单词所在的行数,可能多个行的单词相等
    		void init(){
    			memset(next,0,sizeof(next));
    			line.clear();
    			fail = val = 0;
    		}
    	}ch[maxnode];	//用来存储Trie树
    	int sz;							//整棵树节点的总数 
    	int idx(char c){
    		return c - 'a';		//对于小写字母集,获得c的编号
    	}
    
    	void init(){
    		sz = 1;
    		ch[0].init();
    	}
    	void insert(char *s,int v){
    		int u = 0,len = strlen(s);
    		for(int i = 0 ; i < len ; i ++){
    			int c = idx(s[i]);
    			if(ch[u].next[c] == 0){		
    				ch[sz].init();
    				ch[u].next[c] = sz++;	
    			}
    			u = ch[u].next[c];
    		}
    		ch[u].val  = 1;
    		ch[u].line.push_back(v);
    	}
    
    	//利用bfs得到失配指针fail
    	void get_fail(){
    		queue<int>Q;
    		for(int i = 0 ; i < sigma_size; i ++)
    			if(ch[0].next[i] != 0)
    				Q.push(ch[0].next[i]);
    		while(!Q.empty()){
    			int temp = Q.front();
    			Q.pop();
    			for(int i = 0 ; i < sigma_size; i ++){
    				if(ch[temp].next[i] != 0){
    					Q.push(ch[temp].next[i]);
    					int fail_temp = ch[temp].fail;
    					//关键步骤,如果fail指针所指的节点没有('a'+i)这个子节点,继续递归,直到fail_temp指向0节点,即根节点
    					while(fail_temp > 0 && ch[fail_temp].next[i] == 0) 
    						fail_temp = ch[fail_temp].fail;
    
    					if(ch[fail_temp].next[i] != 0)	//如果fail_temp节点的子节点有('a'+i)这个字符
    							fail_temp = ch[fail_temp].next[i];
    					ch[ch[temp].next[i]].fail = fail_temp;   //子节点的失配节点由父节点节点决定
    				}
    			}
    		}
    	}
    
    	//寻找text[]总共有多少个单词
    	void find(char *text,int x){
    		int len = strlen(text);
    		int node = 0,fail_temp = 0;
    		for(int i = 0 ; i < len ; i ++){
    			int character = idx(text[i]);
    			while(fail_temp > 0 && ch[fail_temp].next[character] == 0)	
    				//若没有text[i]这个字符,则使用失配指针继续在Trie树上遍历
    					fail_temp = ch[fail_temp].fail;
    
    			if(ch[fail_temp].next[character] != 0){	//此时找到了text[i]这个字符
    				fail_temp = ch[fail_temp].next[character];
    				int fail_temp2 = fail_temp;			//此处必须有另一个变量来记录失配的时候的下标
    				while(fail_temp2 > 0 && ch[fail_temp2].val){   
    					for(int j = 0 ; j < ch[fail_temp2].line.size(); j ++){
    						//枚举该单词所在的所有行
    						int temp = ch[fail_temp2].line[j];
    						if(x >= temp)
    							cnt[x-temp][i] ++;
    					}
    					fail_temp2 = ch[fail_temp2].fail;	
    				}
    			}
    		}
    	}
    }AC;
    
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		AC.init();
    		memset(cnt,0,sizeof(cnt));
    		scanf("%d%d",&N,&M);
    		for(int i = 0 ; i < N ; i ++)
    			scanf("%s",map[i]);
    		scanf("%d%d",&X,&Y);
    		char str_temp[105];
    		for(int i = 0 ; i < X; i++){
    			scanf("%s",str_temp);
    			AC.insert(str_temp,i);
    		}
    		AC.get_fail();
    		for(int i = 0 ; i < N ; i++){
    			AC.find(map[i],i);
    		}
    		int ans = 0;
    		for(int i = 0 ; i < N; i ++){
    			for(int j = 0 ; j < M ; j ++){
    				if(cnt[i][j] == X)
    					ans++;
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }


  • 相关阅读:
    fzu 2138
    hdu 1598 暴力+并查集
    poj 1734 floyd求最小环,可得到环上的每个点
    floyd求最小环 模板
    fzu 2087并查集的运用求最小生成树的等效边
    hdu 2586 lca在线算法(朴素算法)
    CF 602 D. Lipshitz Sequence 数学 + 单调栈 + 优化
    Problem 2238 Daxia & Wzc's problem 1627 瞬间移动
    D. Tavas and Malekas DFS模拟 + kmp + hash || kmp + hash
    K-th Number 线段树的区间第K大
  • 原文地址:https://www.cnblogs.com/james1207/p/3347998.html
Copyright © 2020-2023  润新知