矩阵匹配 AC自动机 或 二维Hash UVa 11019 - Matrix Matcher
2015-09-24 23:29
387 查看
题意:给出一个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的那些就是一个二维匹配点.
注意:模式串有可能相同,因此需要一个链表来相同的模式串.
分析:要想整个矩阵匹配,至少各行都得匹配。所以先把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的那些就是一个二维匹配点.
注意:模式串有可能相同,因此需要一个链表来相同的模式串.
#include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXNODE = 10005; const int SIGMA_SIZE = 127; const int N = 1005; const int M = 105; struct AutoMac { int ch[MAXNODE][SIGMA_SIZE]; int val[MAXNODE][105]; int vn[MAXNODE]; int next[MAXNODE]; int last[MAXNODE]; int sz; int n, m, x, y; char nm , xy[M]; int rc ; void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } int idx(char c) { return c; } void insert(char *s, int v) { int u = 0; int n = strlen(s); for (int i = 0; i < n; i++) { int c = idx(s[i]); if (!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); memset(val[sz], 0, sizeof(val[sz])); vn[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u][vn[u]++] = v; } void getnext() { next[0] = 0; queue<int> Q; for (int c = 0; c < SIGMA_SIZE; c++) { int u = ch[0][c]; if (u) {next[u] = 0; Q.push(u); last[u] = 0;} } while (!Q.empty()) { int r = Q.front(); Q.pop(); for (int c = 0; c < SIGMA_SIZE; c++) { int u = ch[r][c]; if (!u) { ch[r][c] = ch[next[r]][c]; continue; } Q.push(u); int v = next[r]; while (v && !ch[v][c]) v = next[v]; next[u] = ch[v][c]; last[u] = val[next[u]] ? next[u] : last[next[u]]; } } } void print(int r, int c, int j) { if (j) { for (int i = 0; i < vn[j]; i++) { if (r - val[j][i] >= 0) rc[r - val[j][i]][c]++; } print(r, c, last[j]); } } void find(int row) { int u = 0; int n = strlen(nm[row]); for (int i = 0; i < n; i++) { int c = idx(nm[row][i]); u = ch[u][c]; if (val[u]) print(row, i - y + 1, u); else if (last[u]) print(row, i - y + 1, last[u]); } } void solve() { memset(rc, 0, sizeof(rc)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%s", nm[i]); scanf("%d%d", &x, &y); for (int i = 1; i <= x; i++) { scanf("%s", xy); insert(xy, i); } getnext(); for (int i = 1; i <= n; i++) find(i); int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (rc[i][j] == x) ans++; } } printf("%d\n", ans); } }; AutoMac gao; int main() { int t; scanf("%d", &t); while (t--) { gao.init(); gao.solve(); } return 0; }
二维Hash
#include <cstdio> #include <cstring> typedef unsigned long long ull; const ull X1 = 100000007, X2 = 1000000007; const int N = 1005; const int M = 105; int t, n, m, x, y; char a , b[M][M]; ull H ; ull gethash() { ull ans = 0; for (int i = 0; i < x; i++) { ull u = 0; for (int j = 0; j < y; j++) u = u * X1 + b[i][j]; ans = ans * X2 + u; } return ans; } int solve() { ull u = gethash(), Hp = 1; for (int i = 0; i < y - 1; i++) Hp *= X1; for (int i = 0; i < n; i++) { ull sum = 0; for (int j = 0; j < y - 1; j++) sum = sum * X1 + a[i][j]; for (int j = y - 1; j < m; j++) { sum = sum * X1 + a[i][j]; H[i][j - y + 1] = sum; sum -= Hp * a[i][j - y + 1]; } } int ans = 0; Hp = 1; for (int i = 0; i < x - 1; i++) Hp *= X2; for (int j = 0; j < m - y + 1; j++) { ull sum = 0; for (int i = 0; i < x - 1; i++) sum = sum * X2 + H[i][j]; for (int i = x - 1; i < n; i++) { sum = sum * X2 + H[i][j]; if (sum == u) ans++; sum -= Hp * H[i - x + 1][j]; } } return ans; } int main() { scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%s", a[i]); scanf("%d%d", &x, &y); for (int i = 0; i < x; i++) scanf("%s", b[i]); printf("%d\n", solve()); } return 0; }
相关文章推荐
- kafka-web-console编译问题
- Python 垃圾回收 (十六)
- 2.5-tomcat配置和优化
- onActivityResult不回调的问题的解决记录
- svn冲突问题详解 SVN版本冲突解决详解
- codota 搜索Android源码
- leetcode7
- ContentProvider和Uri详解
- Android Studio加载第三方jar包,出现包重复加载的问题解决(:app:compileInsideDebugJava FAILED)
- Bob大叔观OO原则
- 关于仿网易新闻中详细页图文混排功能的实现
- 第3章 预处理
- nginx防止爬虫
- MongoDB使用mapReduce实例
- 【转载】C# 中Session的用法
- [Android]init.rc的语法 Android Init Language
- Web API之消息处理管道
- centos 6.6 安装 gcc 4.9.1
- Android 实现m3u8视频缓存
- UVA1423Guess (dfs,bfs拓扑排序)