UVA 11019

Problem H
Matrix Matcher
Input: Standard Input

Output: Standard Output

Given an N * M matrix, your task is to find the number of occurences of an X * Y pattern.

Input

The first line contains a single integer t(t ≤ 15), the number of test cases.

For each case, the first line contains two integers N and M (N, M ≤ 1000). The next N lines contain M characters each.

The next line contains two integers X and Y (X, Y ≤ 100). The next X lines contain Y characters each.

Output

For each case, output a single integer in its own line, the number of occurrences.

Sample Input                               Output for Sample Input

2 
1 1
x 
1 1
y 
3 3
abc 
bcd
cde 
2 2
bc
cd

0

2

 

 

一个二维的hash,可以先对每一行hash,然后在对列hash

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string.h>
 4 #include<vector>
 5 #include<algorithm>
 6 #include<map>
 7 using namespace std;
 8 typedef unsigned long long ull;
 9 #define mmax 100000+10
10 ull base,seed=131,ansx[1100][1100],ansy[1100][1100],aans[1001000];
11 int n,m;
12 char p[1100][1100],q[110][110];
13 int lfind(ull tail){
14     int l=0,r=n*m-1,mid,ans=-1;
15     while(l<=r){
16         mid=(l+r)>>1;
17         if(aans[mid]>=tail) {
18             if(aans[mid]==tail) ans=mid;
19             r=mid-1;
20         }
21         else l=mid+1;
22     }
23     return ans;
24 }
25 int rfind(ull tail){
26     int l=0,r=n*m-1,mid,ans=-1;
27     while(l<=r){
28         mid=(l+r)>>1;
29         if(aans[mid]<=tail) {
30             if(aans[mid]==tail) ans=mid;
31             l=mid+1;
32         }
33         else r=mid-1;
34     }
35     return ans;
36 }
37 int main(){
38     int t;cin>>t;
39     while(t--){
40         cin>>n>>m;getchar();
41         for(int i=0;i<n;i++)
42            scanf("%s",p[i]);
43       //     cout<<"------"<<endl;
44         int x,y;
45         cin>>x>>y;
46         for(int i=0;i<x;i++)
47             scanf("%s",q[i]);
48        // cout<<"------"<<endl;
49         if(x>n||y>m){
50             cout<<0<<endl;
51             continue;
52         }
53         memset(ansx,0,sizeof(ansx));
54         base=1;
55         for(int i=1;i<y;i++) base*=seed;
56         for(int i=0;i<n;i++){
57             for(int j=0;j<y;j++) ansx[i][0]=ansx[i][0]*seed+p[i][j];
58             for(int j=y;j<m;j++) ansx[i][j-y+1]=(ansx[i][j-y]-p[i][j-y]*base)*seed+p[i][j];
59         }
60         memset(ansy,0,sizeof(ansy));
61         base=1;
62         for(int i=1;i<x;i++) base*=seed;
63         for(int i=0;i<m;i++){
64             for(int j=0;j<x;j++) ansy[0][i]=ansy[0][i]*seed+ansx[j][i];
65             for(int j=x;j<n;j++) ansy[j-x+1][i]=(ansy[j-x][i]-ansx[j-x][i]*base)*seed+ansx[j][i];
66         }
67         int id=0;
68         for(int i=0;i<n;i++)
69             for(int j=0;j<m;j++)
70             aans[id++]=ansy[i][j];
71         sort(aans,aans+id);
72         ull tail=0;
73         for(int i=0;i<x;i++){
74             ull tmp=0;
75             for(int j=0;j<y;j++) tmp=tmp*seed+q[i][j];
76             tail=tail*seed+tmp;
77         }
78         if(lfind(tail)==-1){
79             cout<<0<<endl;
80             continue;
81         }
82         printf("%d\n",rfind(tail)-lfind(tail)+1);
83     }
84 }
时间: 2024-10-24 02:52:24

UVA 11019的相关文章

uva 11019 - Matrix Matcher(AC自动机)

题目链接:uva 11019 - Matrix Matcher 题目大意:给出一个n?m的字符矩阵T,要求找出给定r?c的字符矩阵P在T中出现的次数. 解题思路:对P矩阵中的每一行做一个字符串,形成一个字符串集合.构建AC自动机,然后对T矩阵中的每一行进行一次查找,对应出现在该字符串中的子串对应位置+1,如果有一个位置上r次匹配,那么就存在一个匹配矩阵. #include <cstdio> #include <cstring> #include <queue> #inc

UVa 11019 Matrix Matcher - Hash

题目传送门 快速的vjudge传送门 快速的UVa传送门 题目大意 给定两个矩阵S和T,问T在S中出现了多少次. 不会AC自动机做法. 考虑一维的字符串Hash怎么做. 对于一个长度为$l$的字符串$s$,它的Hash值$hash(s) = \sum_{i = 1}^{l}x^{l - i}s_{i}$. 对于二维的情况,我们就取两个基,$x, y$,对于一个$n\times m$的矩阵$A$的Hash值可以表示为 $hash(A) = \sum_{i = 1}^{n}\sum_{j = 1}^

UVA - 11019 Matrix Matcher hash+KMP

题目链接:https://vjudge.net/problem/UVA-11019 题解: 赶着回寝室 明天写题解 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii

UVA 11019 字符矩阵哈希

思路:以前没做过字符矩阵的哈希,所以这题是看别人博客写的. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set>

UVA 11019(Matrix Matcher-vector从迭代器中取值,AC自动机匹配字符矩阵)

Problem H Matrix Matcher Input: Standard Input Output: Standard Output Given an N * M matrix, your task is to find the number of occurences of an X * Y pattern. Input The first line contains a single integer t(t ≤ 15), the number of test cases. For e

UVA 11019 Matrix Matcher 二维的字符串匹配 ac自动机

只要把每行的模版串插到ac自动机,然后匹配行,每次匹配成功,那一行对应的字符矩阵的左上角的计数器+1,最后统计下计数器矩阵有多少个左上角是行数的就可以了. 思路很简单,但想法很好,但要注意模版上有两行是一样的,插入到ac自动机的时候会插到同一个结点上,为了区分,我还是谨慎地开了个vector,然后1A了. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,s

uva 11019 Matrix Matcher

题意:给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P在T中出现了多少次. 思路:要想整个矩阵匹配,至少各行都得匹配.所以先把P的每行看做一个模式串构造出AC自动机,然后在T中的各行逐一匹配,找到P中每一行的所有匹配点. 只要在匹配时做一些附加操作,就可以把匹配出来的单一的行拼成矩形.用一个count[r][c]表示T中一(r,c)为右上角,与P等大的矩形中有多少个 完整的行和P对应位置的行完全相同.当P的第i行出现在T的第r行,起始列编号为c时,意味着count[r-i][c

UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher

就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次出现的位置.如果repr[i] == i,说明这个模式串之前没有重复过,可以加进自动机里去.有重复的话,把这些重复的模式串组织成一个链表,用next把它们连接起来. 所以在统计cnt的时候,匹配到的模式串可能会作为匹配的第i行,也可能是next[i]行,next[next[i]]行等等. 1 #in

AC自动机(二维) UVA 11019 Matrix Matcher

题目传送门 题意:训练之南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include <bits/stdc++.h> using namespace std; const int N = 1e3 + 5; const int NODE = 1e4 + 5; const int SIZE = 26; char mat1[N][N], mat2[105][105]; int cnt[N