UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++;
还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次出现的位置。如果repr[i] == i,说明这个模式串之前没有重复过,可以加进自动机里去。有重复的话,把这些重复的模式串组织成一个链表,用next把它们连接起来。
所以在统计cnt的时候,匹配到的模式串可能会作为匹配的第i行,也可能是next[i]行,next[next[i]]行等等。
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; int n, m, x, y, tr;
const int maxx = + ;
const int maxn = + ;
const int maxnode = + ;
const int sigma_size = ;
char T[maxn][maxn], P[maxx][maxx];
int cnt[maxn][maxn];
int repr[maxx];
int next[maxx]; struct AhoCorasickAutomata
{
int ch[maxnode][sigma_size];
int f[maxnode];
int last[maxnode];
int val[maxnode];
int sz; void init() { sz = ; memset(ch[], , sizeof(ch[])); } inline int idx(char c) { return c - 'a'; } 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];
}
val[u] = v;
} void match(int i, int j)
{
int c = i - y + ;
int pr = repr[val[j] - ];
while(pr >= )
{
if(tr - pr >= ) cnt[tr-pr][c]++;
pr = next[pr];
}
} void print(int i, int j)
{//在文本串的第i列匹配到单词节点j
if(j)
{
match(i, j);
print(i, last[j]);
}
} void find(char* T)
{
int j = , n = strlen(T);
for(int i = ; i < n; i++)
{
int c = idx(T[i]);
while(j && !ch[j][c]) j = f[j];
j = ch[j][c];
if(val[j]) print(i, j);
else if(val[last[j]]) print(i, last[j]);
}
} void getFail()
{
queue<int> q;
f[] = ;
for(int c = ; c < sigma_size; c++)
{
int u = ch[][c];
if(u) { f[u] = ; last[u] = ; q.push(u); }
}
while(!q.empty())
{
int r = q.front(); q.pop();
for(int c = ; c < sigma_size; c++)
{
int u = ch[r][c];
if(!u) 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]];
}
}
}
}ac; int main()
{
//freopen("in.txt", "r", stdin); int test;
scanf("%d", &test);
while(test--)
{
scanf("%d%d", &n, &m);
for(int i = ; i < n; i++) scanf("%s", T[i]);
scanf("%d%d", &x, &y);
ac.init();
for(int i = ; i < x; i++)
{
repr[i] = i;
next[i] = -;
scanf("%s", P[i]);
for(int j = ; j < i; j++) if(strcmp(P[i], P[j]) == )
{
repr[i] = j;
next[i] = next[j];
next[j] = i;
break;
}
if(repr[i] == i) ac.insert(P[i], i+);
}
ac.getFail();
memset(cnt, , sizeof(cnt));
for(tr = ; tr < n; tr++) ac.find(T[tr]); int ans = ;
for(int i = ; i < n; i++)
for(int j = ; j < m; j++)
if(cnt[i][j] == x) ans++;
printf("%d\n", ans);
} return ;
}
代码君
UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher的更多相关文章
- UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...
- pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!
/** 题目:pku1204 Word Puzzles 链接:http://poj.org/problem?id=1204 题意:给定一个L C(C <= 1000, L <= 1000) ...
- AC自动机(二维) UVA 11019 Matrix Matcher
题目传送门 题意:训练指南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include ...
- 模板—字符串—AC自动机(多模式串,单文本串)
模板—字符串—AC自动机(多模式串,单文本串) Code: #include <queue> #include <cstdio> #include <cstring> ...
- 二维码Data Matrix的解码实现(zxing-cpp)
二维码Data Matrix的介绍可以参考http://blog.csdn.net/fengbingchun/article/details/44279967 ,以下是通过zxing-cpp开源库实现 ...
- 二维码Data Matrix编码、解码使用举例
二维码Data Matrix的介绍见: http://blog.csdn.net/fengbingchun/article/details/44279967 ,这里简单写了个生成二维码和对二维码进行 ...
- UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串
链接:https://vjudge.net/problem/UVA-11019lrjP218 matrix matcher #include<bits/stdc++.h> using na ...
- UVA - 11468 (AC自动机+动态规划)
建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...
- Uva 11468 AC自动机或运算
AC自动机 UVa 11468 题意:给一些字符和各自出现的概率,在其中随机选择L次,形成长度为L的字符串S,给定K个模板串,求S不包含任意一个串的概率. 首先介绍改良版的AC自动机: 传统的AC自动 ...
随机推荐
- jQuery中的Deferred-详解和使用
首先,为什么要使用Deferred? 先来看一段AJAX的代码: var data; $.get('api/data', function(resp) { data = resp.data; }); ...
- PHP命名空间(Namespace)
http://www.jb51.net/article/36389.htm 字符串形式的动态调用方式 //魔法常量__NAMESPACE__的值是当前空间名称 //可以组合成字符串并调用 $comme ...
- iOS-OpenGLES 简单渲染
UIImage *showImage = [UIImage imageNamed:, , showImage.size.width, showImage.size.height); ) fo ...
- Javascript 数组循环遍历之forEach
1. js 数组循环遍历. 数组循环变量,最先想到的就是 for(var i=0;i<count;i++)这样的方式了. 除此之外,也可以使用较简便的forEach 方式 2. forE ...
- 在Jmeter中使用自定义编写的Java测试代码
我们在做性能测试时,有时需要自己编写测试脚本,很多测试工具都支持自定义编写测试脚本,比如LoadRunner就有很多自定义脚本的协议,比如"C Vuser","Java ...
- Struts2 中的值栈的理解
通过对struts2的一段时间的接触,将自己对OGNL的核心值栈说说,值栈:简单的说,就是存放action的堆栈,当我们提交一个请求 道服务器端 action时,就有个堆栈,如果action在服务器端 ...
- C语言连接Oracle (转载)
最近在搞C语言连接Oracle.DB2数据库,现把C连接Oracle的文章总结下: 用C语言连接ORACLE数据库.有两个思路和目的 思路一)本地环境:UBUNTU 7.04,ORACLE 10G目的 ...
- Struts2笔记——文件上传
文件上传概述 * 要想使用HTML 表单上传一个或多个文件, 必须把 HTML 表单的 enctype 属性设置为multipart/form-data,把它的 method 属性设置为post * ...
- Phalanx--hdu2859(dp 最大对称子图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2859 题意就是给你一个n*n的字符矩阵,从中选出一个最大的子矩阵(m*m)满足关于斜对角线(左下角到右 ...
- Linux任务前后台的切换
Shell支持作用控制,有以下命令实现前后台切换: 1. command& 让进程在后台运行 2. jobs 查看后台运行的进程 3. fg %n 让后台运行的进程n到前台来 4. bg %n ...