UVA 11019 Matrix Matcher——AC自动机
来源:互联网 发布:国际淘宝城 编辑:程序博客网 时间:2024/06/16 11:05
首先将模式矩阵的每一行看做一个模式串,建立字典树
然后构造fail指针
然后把文本矩阵的每一行拿出来,作为一个文本串去匹配构造好的AC自动机
这里先给出cnt【i】【j】的概念:文本矩阵中以(i,j)位置作为右上角、与模式矩阵等大的矩阵中有多少个完整的行和模式矩阵对应的行完全匹配,这个方法很巧妙,用心理解。(注:一些教材用了左上角,其实都可以,右上角更好写)
假设现在你从文本矩阵中拿出了第row行作为文本串进行匹配,恰好匹配到了模式矩阵的第id行(构造字典树时把节点值赋为行编号),此时文本串匹配到了第i为,那么右上角就是(row - id, i)(当然要保证row>=id),此时把cnt【row-id】【i】++
最后统计一下cnt中有多少个位置等于模式矩阵的行数就可以了
注意题目中会有相同的模式串,需要用链表保存
为什么用cnt数组求解是可行的呢?cnt中存的是这个位置代表的矩阵与模式矩阵成功匹配的行数,如果行数等于模式矩阵的行数那么这个位置就是一个可行位置,如果这些行都不相同的话那么一定没问题,但是如果有一行为cnt贡献了多次数值,那么不就出错了吗?但是,同一行贡献多次数值得情况只会出现在一个文本串和一个模式串多次匹配的情况,这在本题中是不允许的。(AC自动机的重复匹配只适用于一个模式串包含另一个模式串的情况,而这道题所有模式串等长,不会出现包含情况)
以上只是个人片面的理解,如有错误欢迎指正!
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>using namespace std;const int maxn = 105 * 105;const int SIZE = 26;char P[105][105], T[1005][1005];int Kase, n, m, x, y, ans, cnt[1005][1005];struct AC { int total, val[maxn], fail[maxn], next[maxn], child[maxn][SIZE]; void init() { total = 1; memset(val, 0, sizeof(val)); memset(fail, 0, sizeof(fail)); memset(next, 0, sizeof(next)); memset(child[0], 0, sizeof(child[0])); } void Insert(char *str, int id) { int root = 0; for (int i = 0; str[i]; i++) { if (!child[root][str[i] - 'a']) { memset(child[total], 0, sizeof(child[total])); child[root][str[i] - 'a'] = total++; } root = child[root][str[i] - 'a']; } next[id] = val[root]; val[root] = id; } void Getfail() { queue<int> q; for (int i = 0; i < SIZE; i++) { if (child[0][i]) q.push(child[0][i]); } while (!q.empty()) { int root = q.front(); q.pop(); for (int i = 0; i < SIZE; i++) { int u = child[root][i]; if (!u) { child[root][i] = child[fail[root]][i]; continue; } q.push(u); int v = fail[root]; while (v && !child[v][i]) v = fail[v]; fail[u] = child[v][i]; } } } void Search(char *str, int row) { int root = 0, temp = 0; for (int i = 0; str[i]; i++) { temp = root = child[root][str[i] - 'a']; while (temp && val[temp]) { if (row - val[temp] >= 0) cnt[row - val[temp]][i]++; for (int t = next[val[temp]]; t; t = next[t]) { if (row >= t) cnt[row - t][i]++; } temp = fail[temp]; } } }}ac;int main() { scanf("%d", &Kase); while (Kase--) { ans = 0; memset(cnt, 0, sizeof(cnt)); ac.init(); scanf("%d %d", &m, &n); for (int i = 1; i <= m; i++) scanf("%s", T[i]); scanf("%d %d", &x, &y); for (int i = 1; i <= x; i++) { scanf("%s", P[i]); ac.Insert(P[i], i); } ac.Getfail(); for (int i = 1; i <= m; i++) ac.Search(T[i], i); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (cnt[i][j] == x) ans++; } } printf("%d\n", ans); } return 0;}
阅读全文
1 0
- UVA 11019 Matrix Matcher——AC自动机
- UVa:11019 Matrix Matcher(AC自动机)
- uva 11019 - Matrix Matcher(AC自动机)
- uva 11019 - Matrix Matcher --AC自动机
- UVA-11019 - Matrix Matcher(AC自动机)
- UVA 11019 Matrix Matcher(AC自动机)
- AC自动机(Matrix Matcher,UVA 11019)
- UVA-11019Matrix Matcher(AC自动机)
- 11019 - Matrix Matcher--AC自动机
- UVa 11019 Matrix Matcher AC自动机 二维匹配
- UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
- UVA 11019 Matrix Matcher(AC自动机矩阵匹配)
- UVA 11019 Matrix Matcher(AC自动机:矩阵匹配)
- UVA 11019 - Matrix Matcher(AC自动机 | hash大法)
- UVA 11019 Matrix Matcher AC自动机字符串矩阵匹配
- uva 11019 Matrix Matcher (ac自动机二维匹配)
- UVA 11019 Matrix Matcher(二维矩阵匹配ac自动机)
- UVA 1019 Matrix Matcher(AC自动机)
- mycat学习02之mycat的相关概念
- 卡顿问题综述
- Linq 多层嵌套查询
- BZOJ 3109: [cqoi2013]新数独 dfs
- h5新增的内容和api
- UVA 11019 Matrix Matcher——AC自动机
- Android apk瘦身讲解
- Android开发之线程与线程池
- I Hate It 树状数组 单点更新 区间最大值
- BZOJ 1007 水平可见直线 几何(半凸包)
- RC4加密
- php 开发调试的常用技巧和工具
- 线程范围内共享数据
- qt中xml的一些补充知识点