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自动 ...
随机推荐
- laravel5学习手记
0.autoload 基本用法: http://docs.phpcomposer.com/01-basic-usage.html#Autoloading 一个讲解: http://www.jb51. ...
- Windows Server2008+IIS7部署网站的日期格式问题
最近部署一个ASP网站,发现网站的某个功能上的日历在原来的服务器上访问时是会根据特定日期来对该日进行加粗加红显示的,但部署到我公司机房的win2008服务器上访问时却没有这效果了. 于是通过本地部署, ...
- 在运行jar时自动加载指定的jar包
初学Java的人经常遇到的一个问题是:如果一个程序依赖某个文件夹下的一堆jar包,那么启动它的时候就需要在java -cp参数后面一个一个的加上jar包的名称,很不方便. 比如主程序类叫Main,在目 ...
- ExtJs布局之tabPanel
<!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...
- 高性能js之js加载执行
转载自:http://www.blogjava.net/BearRui/archive/2010/04/08/web_performance_js_where.html 外部JS的阻塞下载 所有浏览器 ...
- vim使用详解
1 插入类命令 i // 在当前字符前插入 I // 在当前行首插入 a // 在当前字符后写入 A ...
- Tomcat SSL 设置
1. 先用如下命令生成tomcat 证书 cls rem please set the env JAVA_HOME before run this bat file SET JAVA_HOME=C:\ ...
- python_pycharm介绍1
1. 常用设置 修改编程风格 File-Setting中,Editor下Colors&Fonts修改即可调整风格. 修改字体大小 pycharm默认字体太小,需调整些,Settings--&g ...
- CentOS 加载/挂载 U盘
1.以root用户登陆 先加载USB模块 modprobe usb-storage 用fdisk -l 看看U盘的设备 假如U盘是sda1 2.确定在 目录 /mnt 下建立了 文件夹 ...
- C++:delete和delete[]释放内存的区别
C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]. 关于 new[] 和 delete[], ...