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][N];
int n, m, x, y;
struct AC {
int ch[NODE][SIZE], val[NODE], sz;
int fail[NODE], last[NODE];
vector<int> rows[NODE];
void clear(void) {
memset (ch[0], 0, sizeof (ch[0]));
sz = 1;
for (int i=0; i<NODE; ++i) rows[i].clear ();
}
int idx(char c) {
return c - 'a';
}
void insert(char *P, int v) {
int u = 0;
for (int c, i=0; P[i]; ++i) {
c = idx (P[i]);
if (!ch[u][c]) {
memset (ch[sz], 0, sizeof (ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;
rows[u].push_back (v);
}
void build(void) {
queue<int> que; fail[0] = 0;
int u;
for (int c=0; c<SIZE; ++c) {
u = ch[0][c];
if (u) {fail[u] = 0; que.push (u);}
}
while (!que.empty ()) {
int r = que.front (); que.pop ();
for (int c=0; c<SIZE; ++c) {
int &u = ch[r][c];
if (!u) {
u = ch[fail[r]][c];
continue;
}
que.push (u);
int v = fail[r];
while (v && !ch[v][c]) v = fail[v]; //
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}
void query(int row) {
int u = 0;
for (int c, i=0; mat1[row][i]; ++i) {
c = idx (mat1[row][i]);
u = ch[u][c];
if (i - y + 1 < 0) continue;
if (val[u]) print (row, i - y + 1, u);
else if (last[u]) print (row, i - y + 1, last[u]);
}
}
void print(int r, int c, int u) {
if (u) {
for (int i=0; i<rows[u].size (); ++i) {
int tr = rows[u][i];
if (r - tr + 1 >= 1) {
cnt[r-tr+1][c]++;
}
}
print (r, c, last[u]);
}
}
}ac; int main(void) {
int T; scanf ("%d", &T);
while (T--) {
scanf ("%d%d", &n, &m);
for (int i=1; i<=n; ++i) {
scanf ("%s", &mat1[i]);
}
ac.clear ();
scanf ("%d%d", &x, &y);
for (int i=1; i<=x; ++i) {
scanf ("%s", &mat2[i]);
ac.insert (mat2[i], i);
}
ac.build ();
memset (cnt, 0, sizeof (cnt));
for (int i=1; i<=n; ++i) {
ac.query (i);
}
int ans = 0;
for (int i=1; i<=n-x+1; ++i) {
for (int j=0; j<=m-y; ++j) {
if (cnt[i][j] == x) ans++;
}
}
printf ("%d\n", ans);
} return 0;
}
AC自动机(二维) UVA 11019 Matrix Matcher的更多相关文章
- UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次 ...
- UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...
- UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串
链接:https://vjudge.net/problem/UVA-11019lrjP218 matrix matcher #include<bits/stdc++.h> using na ...
- UVA - 11019 Matrix Matcher (二维字符串哈希)
给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数. 看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希. 类比一维情况下的哈希算法,利用容斥 ...
- UVA 11019 Matrix Matcher(ac自动机)
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 11019 Matrix Matcher(二维hash + 尺取)题解
题意:在n*m方格中找有几个x*y矩阵. 思路:二维hash,总体思路和一维差不太多,先把每行hash,变成一维的数组,再对这个一维数组hash变成二维hash.之前还在想怎么快速把一个矩阵的hash ...
- UVa 11019 Matrix Matcher - Hash
题目传送门 快速的vjudge传送门 快速的UVa传送门 题目大意 给定两个矩阵S和T,问T在S中出现了多少次. 不会AC自动机做法. 考虑一维的字符串Hash怎么做. 对于一个长度为$l$的字符串$ ...
- uva 11019 Matrix Matcher
题意:给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P在T中出现了多少次. 思路:要想整个矩阵匹配,至少各行都得匹配.所以先把P的每行看做一个模式串构造出AC自动机,然后在T中的各行 ...
- UVA 11019 Matrix Matcher(哈希)
题意 给定一个 \(n\times m\) 的矩阵,在给定一个 \(x\times y\) 的小矩阵,求小矩阵在大矩阵中出现的次数. \(1 \leq n,m \leq 1000\) \(1\leq ...
随机推荐
- IOS- 堆和栈 详解
Objective-C的对象在内存中是以堆的方式分配空间的,并且堆内存是由你释放的,即release 栈由编译器管理自动释放的,在方法中(函数体)定义的变量通常是在栈内,因此如果你的变量要跨函数的话就 ...
- objective-c字符串笔记
字符串 // 字符串 分可变字符串和不可变字符串 // 不可变字符串的初始化方式 // NSString *string = [[NSString allo ...
- log4j介绍以及使用教程
一.介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接 口服务 器.NT的事件记录器.UNIX Syslog ...
- Spetember 5th 2016 Week 37th Monday
No matter how far you may fly, never forget where you come from. 无论你能飞多远,都别忘了你来自何方. Stay true to you ...
- 多线程编程1 - NSThread
每个iOS应用程序都有个专门用来更新显示UI界面.处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验.一般的解决方案就是将 ...
- 最简单的Web服务器
//读取浏览器发过来的内容Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, Protoco ...
- python基础——多重继承
python基础——多重继承 继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能. 回忆一下Animal类层次的设计,假设我们要实现以下4种动物: Dog - 狗狗: Bat ...
- Java ANT build.xml
详情请参考:http://www.cnblogs.com/xionghui/archive/2012/03/13/2393679.html
- 在 Windows 和 Linux(Gnome) 环境下 从命令界面打开网页的方式
1.在 Windows 中 通过命令 可以打开网页是很简单的: start http://www.baidu.com 或 start iexplorer http://www.baidu.com 第二 ...
- Android 录音
想要实现wav格式的编码时我们也就不能再使用MediaRecorder,而只能使用AudioRecord进行处理