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]应当加1.所有匹配结束后,count[r] [c]=X的那些就是一个二维匹配点.
注意:模式串有可能相同,因此需要一个next数组来记录相同的模式串.
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
const int SIGMA_SIZE = ;
const int MAXNODE = ;
const int MAXS = + ; struct ACautomata
{
int ch[MAXNODE][SIGMA_SIZE];
int f[MAXNODE]; // fail函数
int val[MAXNODE]; // 每个字符串的结尾结点都有一个非0的val
int last[MAXNODE]; // 输出链表的下一个结点
int next[MAXS];
int sz;
int count[][];
void init()
{
sz = ;
memset(ch[], , sizeof(ch[]));
memset(count,,sizeof(count));
memset(next,,sizeof(next));
} // 字符c的编号
int idx(char c)
{
return c-'a';
} // 插入字符串。v必须非0
void insert(char *s, int v)
{
int u = , n = strlen(s);
for(int i = ; i < n; i++)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz], , sizeof(ch[sz]));
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
if(val[u])
{
next[v]=val[u];
}
val[u] = v;
} // 递归打印匹配文本串str[i]结尾的后缀,以结点j结尾的所有字符串
void print(int i,int j,int x)
{
if(j)
{
if(x-val[j]+>)
count[x-val[j]+][i]++;
int t=val[j];
while(next[t])
{
t=next[t];
if(x-t+>)
count[x-t+][i]++;
}
print(i,last[j],x);
}
} // 在T中找模板
int find(char* T,int x)
{
int n = strlen(T);
int j = ; // 当前结点编号,初始为根结点
for(int i = ; i < n; i++) // 文本串当前指针
{
int c = idx(T[i]);
j = ch[j][c];
if(val[j]) print(i,j,x);
else if(last[j]) print(i,last[j],x); // 找到了!
}
} // 计算fail函数
void getFail()
{
queue<int> q;
f[] = ;
// 初始化队列
for(int c = ; c < SIGMA_SIZE; c++)
{
int u = ch[][c];
if(u)
{
f[u] = ;
q.push(u);
last[u] = ;
}
}
// 按BFS顺序计算fail
while(!q.empty())
{
int r = q.front();
q.pop();
for(int c = ; c < SIGMA_SIZE; c++)
{
int u = ch[r][c];
if(!u)
{
ch[r][c]=ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while(v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
} };
ACautomata solver;
char str[][];
char str1[][];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int N,M,X,Y;
scanf("%d%d",&N,&M);
for(int i=; i<=N; i++)
scanf("%s",str[i]);
scanf("%d%d",&X,&Y);
for(int i=; i<=X; i++)
scanf("%s",str1[i]);
solver.init();
for(int i=; i<=X; i++)
{
solver.insert(str1[i],i);
}
solver.getFail();
for(int i=; i<=N; i++)
{
solver.find(str[i],i);
}
int ans=;
for(int i=; i<=N; i++)
for(int j=; j<=M; j++)
if(solver.count[i][j]==X)
ans++;
printf("%d\n",ans);
}
return ;
}
uva 11019 Matrix Matcher的更多相关文章
- UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串
链接:https://vjudge.net/problem/UVA-11019lrjP218 matrix matcher #include<bits/stdc++.h> using na ...
- UVa 11019 Matrix Matcher - Hash
题目传送门 快速的vjudge传送门 快速的UVa传送门 题目大意 给定两个矩阵S和T,问T在S中出现了多少次. 不会AC自动机做法. 考虑一维的字符串Hash怎么做. 对于一个长度为$l$的字符串$ ...
- UVA 11019 Matrix Matcher(ac自动机)
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- AC自动机(二维) UVA 11019 Matrix Matcher
题目传送门 题意:训练指南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include ...
- UVA 11019 Matrix Matcher(哈希)
题意 给定一个 \(n\times m\) 的矩阵,在给定一个 \(x\times y\) 的小矩阵,求小矩阵在大矩阵中出现的次数. \(1 \leq n,m \leq 1000\) \(1\leq ...
- UVA 11019 Matrix Matcher(二维hash + 尺取)题解
题意:在n*m方格中找有几个x*y矩阵. 思路:二维hash,总体思路和一维差不太多,先把每行hash,变成一维的数组,再对这个一维数组hash变成二维hash.之前还在想怎么快速把一个矩阵的hash ...
- UVA - 11019 Matrix Matcher (二维字符串哈希)
给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数. 看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希. 类比一维情况下的哈希算法,利用容斥 ...
- UVA - 11019 Matrix Matcher hash+KMP
题目链接:传送门 题解: 枚举每一行,每一行当中连续的y个我们hash 出来 那么一行就是 m - y + 1个hash值,形成的一个新 矩阵 大小是 n*(m - y + 1), 我们要找到x*y这 ...
- UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...
随机推荐
- Deadline来了,如何按时结题?
- PAT-乙级-1029. 旧键盘(20)
1029. 旧键盘(20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 旧键盘上坏了几个键,于是在敲一段文字的 ...
- uva 10056
概率 Q += p*pow(1-p, i*n+k-1) i = 0,1,2,3...... #include <cstdio> #include <cmath> int mai ...
- RCC 2014 Warmup (Div. 2) ABC
题目链接 A. Elimination time limit per test:1 secondmemory limit per test:256 megabytesinput:standard in ...
- POJ1905Expanding Rods(二分)
http://poj.org/problem?id=1905 题意 :在两堵实心墙中间有一根杆,长度为L,然后给它加热,温度是n,则两墙之间的杆会弯曲,长度会变为L'=(1+n*C)*L,求前后两个状 ...
- codeforces #309 div1 B
题目啰里啰嗦说了一大堆(耐心读完题目就可以秒题了) 首先我们考虑当前置换的开头的循环节的开头 1.如果是1 1->1形成循环节 问题变成i-1的子问题 2.如果是2 1->2->1形 ...
- 221. Maximal Square
题目: Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ...
- 最短路径算法之二——Dijkstra算法
Dijkstra算法 Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 注意该算法要求图中不存在负权边. 首先我们来定义一个二维数组Edge[MAXN][MAXN]来存储 ...
- Java读写Windows共享文件夹 .
版权声明:本文为博主原创文章,未经博主允许不得转载. 项目常常需要有访问共享文件夹的需求,例如共享文件夹存储照片.文件等.那么如何使用Java读写Windows共享文件夹呢? Java可以使用JCIF ...
- CodePage------Encoding 类支持的编码以及与这些编码关联的代码页(CodePage)
Encoding 类 .NET Framework 4 表示字符编码. 继承层次结构 System.Object System.Text.Encoding System.Text.ASCII ...