UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门
题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S;
问模式串 S 在文本串 T 中出现了多少次。
解:
法一: AC自动机 (正解) 670ms
把模式串的每一行当成一个字符串, 建一个AC自动机。
然后设cnt[ x ][ y ] 表示文本串中,以 (x, y) 这个点为矩阵右上角的点,且矩阵大小为 r * c的矩阵与模式串匹配了多少行。
那最终统计答案的时候, 只需要 o(n * m) 枚举所有点,记录那些 cnt[ x ][ y ] == n 的点 的个数。 就是答案。
那我们建完AC自动机后, 就可以枚举文本串的每一行,让其去跑 建成的AC自动机, 记录匹配情况即可。
文本串的第 x 行和 模式串的 第 i 行匹配, 则, cnt[ x - i + 1][ y ] ++;
我的代码里有一个 nx[ ] 数组, 这个数组的作用是。
若模式串中, 存在多行字符是完全相等的情况, 则你文本串和当前字符串匹配,可能有多种情况。
比如,你模式串的第3行和第5行是完全相等的, 那么, 你要是文本串匹配到了模式串的第3行,那么你也同样匹配到了第5行。
所以,增加nx[]数组来存,同一字符串的不同编号。
#include <bits/stdc++.h>
#define LL long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define mem(i, j) memset(i, j, sizeof(i))
using namespace std; const int N = 1e3 + , M = 1e4 + ; struct Trie {
int ch[M][], val[M], Fail[M], tot, nx[M], last[M], cnt[N][N];
void init() {
mem(ch[], ); val[] = ; tot = ; last[] = ; mem(cnt, ); mem(nx, );
}
int get(char Q) {
return Q - 'a';
}
void join(char s[], int pos) {
int now = ; int len = strlen(s);
rep(i, , len - ) {
int id = get(s[i]);
if(!ch[now][id]) {
mem(ch[tot], ); val[tot] = ; last[tot] = ;
ch[now][id] = tot++;
}
now = ch[now][id];
}
nx[pos] = val[now];
val[now] = pos;
}
void getFail() {
queue<int> Q; while(!Q.empty()) Q.pop();
rep(i, , ) {
if(ch[][i]) {
Q.push(ch[][i]);
Fail[ch[][i]] = ;
last[ch[][i]] = ;
}
}
while(!Q.empty()) {
int now = Q.front(); Q.pop();
rep(i, , ) {
int u = ch[now][i];
if(!ch[now][i]) ch[now][i] = ch[Fail[now]][i];
else {
Q.push(ch[now][i]);
Fail[u] = ch[Fail[now]][i];
last[u] = val[Fail[u]] ? Fail[u] : last[Fail[u]];
}
}
}
}
void add_ans(int x, int y, int u) {
if(u) {
if(x - val[u] + >= ) {
cnt[x - val[u] + ][y]++;
}
int tmp = val[u];
while(nx[tmp]) {
tmp = nx[tmp];
if(x - tmp + >= ) cnt[x - tmp + ][y]++;
}
add_ans(x, y, last[u]);
}
}
void print(char s[], int x) {
int len = strlen(s + ); int now = ;
rep(i, , len) {
int id = get(s[i]);
now = ch[now][id]; if(val[now]) {
add_ans(x, i, now);
}
else if(last[now]) {
add_ans(x, i, last[now]);
}
}
}
};
Trie AC;
char s[][], ss[];
int main() {
int _; scanf("%d", &_);
while(_--) {
AC.init();
int n, m; scanf("%d %d", &n, &m);
rep(i, , n) scanf("%s", s[i] + );
int r, c; scanf("%d %d", &r, &c);
rep(i, , r) {
scanf("%s", ss); AC.join(ss, i);
}
AC.getFail(); ///建AC自动机
rep(i, , n) { /// 对文本串每一行跑AC自动机,记录匹配情况
AC.print(s[i], i);
}
int ans = ;
rep(i, , n) rep(j, , m) {
if(AC.cnt[i][j] == r) ans++;
}
printf("%d\n", ans);
}
return ;
}
法二: 二维Hash 40ms
参考: 博客
#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define mem(i, j) memset(i, j, sizeof(i))
using namespace std;
const int N = 1e3 + ;
const unsigned int hash1 = 1e9 + , hash2 = 1e9 + ;
char a[N][N], b[][];
unsigned int p1[N], p2[N];
unsigned int hs[N][N];
void init() {
p1[] = ; p2[] = ;
rep(i, , N - ) p1[i] = p1[i - ] * hash1, p2[i] = p2[i - ]* hash2;
}
int main() {
int _; scanf("%d", &_); init();
while(_--) {
int n, m; scanf("%d %d", &n, &m);
rep(i, , n) scanf("%s", a[i] + );
int x, y; scanf("%d %d", &x, &y);
rep(i, , x) scanf("%s", b[i] + );
rep(i, , n) rep(j, , m) { /// 预处理n * m矩阵的二维前缀和。(三个方向的前缀和,)
hs[i][j] = hs[i - ][j - ] * hash1 * hash2 + (hs[i - ][j] - hs[i - ][j - ] * hash2) * hash1 + (hs[i][j - ] - hs[i - ][j - ] * hash1) * hash2 + a[i][j];
}
unsigned int S = , C;
rep(i, , x) rep(j, , y) { ///算模式串的hash值
S += b[i][j] * p1[x - i] * p2[y - j];
}
int ans = ;
rep(i, x, n) rep(j, y, m) { ///枚举文本串所有x*y矩阵,o(1)算出它们的hash值
C = hs[i][j] - hs[i - x][j - y] * p1[x] * p2[y] - (hs[i][j - y] - hs[i - x][j - y] * p1[x]) * p2[y] - (hs[i - x][j] - hs[i - x][j - y] * p2[y]) * p1[x];
if(S == C) ans++;
}
printf("%d\n", ans);
}
return ;
}
UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )的更多相关文章
- 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 - 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(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 ...
- 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+KMP
题目链接:传送门 题解: 枚举每一行,每一行当中连续的y个我们hash 出来 那么一行就是 m - y + 1个hash值,形成的一个新 矩阵 大小是 n*(m - y + 1), 我们要找到x*y这 ...
随机推荐
- R学习笔记1 介绍R的使用
R脚本的一次执行叫做一个会话(Session),可以通过函数quit()退出当前的会话 quit(save = "default", status = 0, runLast = T ...
- Luogu4548 CTSC2006 歌唱王国 概率生成函数、哈希
传送门 orz ymd 考虑构造生成函数:设\(F(x) = \sum\limits_{i=0}^\infty f_ix^i\),其中\(f_i\)表示答案为\(i\)的概率:又设\(G(x) = \ ...
- go liteIDE 快捷键
Goland常用快捷键文件相关快捷键: CTRL+E,打开最近浏览过的文件.CTRL+SHIFT+E,打开最近更改的文件.CTRL+N,可以快速打开struct结构体.CTRL+SHIFT+N,可以快 ...
- twbsPagination.js分页插件
分页插件在使用时注意,如果页面中存在其他异步加载的数据,在运行分页方法第一次后,页面上的分页样式与分页中的data数据就是第一次的数据,如果异步加载重新在页面上录入数据,并希望分页继续在新的数据上实现 ...
- Xinetd服务的安装与配置详解
1.什么是xinetd xinetd即extended internet daemon,xinetd是新一代的网络守护进程服务程序,又叫超级Internet服务器.经常用来管理多种轻量级Interne ...
- 深入理解JVM(一) -- 自动内存管理机制
Java运行时数据区域分为:程序计数器,虚拟机栈,本地方法栈,Java堆,方法区,运行时常量池,直接内存,结构如下: 1.程序计数器: 是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示 ...
- 【OO学习】OO第三单元作业总结
[OO学习]OO第三单元作业总结 第三单元,我们学习了JML语言,用来进行形式化设计.本单元包括三次作业,通过给定的JML来实行了一个对路径的管理系统,最后完成了一个地铁系统,来管理不同的线路,求得关 ...
- console.log()、console.info()、console.debug()的区别
onsole.log().console.info().console.debug()的作用都是在浏览器控制台打印信息的. 使用最多的是console.log().console.info()和con ...
- js 一些有意思的小Demo
- 当ajax都完成后执行方法
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...