就向书上说得那样,如果模式串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的更多相关文章

  1. UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )

    题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...

  2. pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!

    /** 题目:pku1204 Word Puzzles 链接:http://poj.org/problem?id=1204 题意:给定一个L C(C <= 1000, L <= 1000) ...

  3. AC自动机(二维) UVA 11019 Matrix Matcher

    题目传送门 题意:训练指南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include ...

  4. 模板—字符串—AC自动机(多模式串,单文本串)

    模板—字符串—AC自动机(多模式串,单文本串) Code: #include <queue> #include <cstdio> #include <cstring> ...

  5. 二维码Data Matrix的解码实现(zxing-cpp)

    二维码Data Matrix的介绍可以参考http://blog.csdn.net/fengbingchun/article/details/44279967 ,以下是通过zxing-cpp开源库实现 ...

  6. 二维码Data Matrix编码、解码使用举例

    二维码Data Matrix的介绍见: http://blog.csdn.net/fengbingchun/article/details/44279967  ,这里简单写了个生成二维码和对二维码进行 ...

  7. UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串

    链接:https://vjudge.net/problem/UVA-11019lrjP218 matrix matcher #include<bits/stdc++.h> using na ...

  8. UVA - 11468 (AC自动机+动态规划)

    建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...

  9. Uva 11468 AC自动机或运算

    AC自动机 UVa 11468 题意:给一些字符和各自出现的概率,在其中随机选择L次,形成长度为L的字符串S,给定K个模板串,求S不包含任意一个串的概率. 首先介绍改良版的AC自动机: 传统的AC自动 ...

随机推荐

  1. 谈谈arm下的函数栈

    引言 这篇文章简要说说函数是怎么传入参数的,我们都知道,当一个函数调用使用少量参数(ARM上是少于等于4个)时,参数是通过寄存器进行传值(ARM上是通过r0,r1,r2,r3),而当参数多于4个时,会 ...

  2. POJ 1001 Exponentiation(JAVA,BigDecimal->String)

    题目 计算实数a的n次方,具体输出格式看案例 import java.util.*; import java.math.*; public class Main { public static voi ...

  3. Static vs Dynamic Scope

    转自:http://hoolihan.net/blog-tim/2009/02/17/static-vs-dynamic-scope/ // start pseudo-code var y = &qu ...

  4. POJ 2785

    4 Values whose Sum is 0 Time Limit: 15000MS   Memory Limit: 228000K Total Submissions: 14475   Accep ...

  5. 【OpenCV入门教程之二】 一览众山小:OpenCV 2.4.8组件结构全解析

    转自: http://blog.csdn.net/poem_qianmo/article/details/19925819 本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:ht ...

  6. Linux多线程之同步3

    需求 客户端将需要解决的task发送给服务器,服务器调用线程来解决客户端发送的task,解决完由线程负责将其发送回客户端.(用管道实现通信) 思路 1. server维护两个列表.一是客户端列表.二是 ...

  7. mysql之select(二)

    union 联合 作用: 把2次或多次查询结果合并起来. 要求:两次查询的列数一致.推荐:查询的每一列,相对应得列类型也一样. 可以来自于多张表.多次sql语句取出的列名可以不一致,此时,以第1个sq ...

  8. 李洪强漫谈iOS开发[C语言-005]-程序结构分析

  9. 叠罗汉II

    叠罗汉是一个著名的游戏,游戏中一个人要站在另一个人的肩膀上.为了使叠成的罗汉更稳固,我们应该让上面的人比下面的人更轻一点.现在一个马戏团要表演这个节目,为了视觉效果,我们还要求下面的人的身高比上面的人 ...

  10. lintcode:两数组的交 II

    题目 计算两个数组的交 注意事项 每个元素出现次数得和在数组里一样答案可以以任意顺序给出 样例 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2]. 解题 ...