LINK1

LINK2


题目大意

让你在一个大小为\(n*m\)的矩阵中找大小是\(x*y\)的矩阵的出现次数

思路1:Hash

hash思路及其傻逼

你把一维情况扩展一下

一维是一个bas,那你二维就用两个bas好了

对一个在\((i,j)\)的字符,令他的hash值是\(c_{i,j}*bas1^i*bas2^j\)

然后算出矩阵hash值乘上差量判断就做完了

70ms


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
typedef pair<int, int> pi;
typedef long long ll;
typedef double db;
#define fi first
#define se second
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
template <typename T>
void Read(T &x) {bool w = 1;x = 0;char c = getchar();while (!isdigit(c) && c != '-') c = getchar();if (c == '-') w = 0, c = getchar();while (isdigit(c)) {x = (x<<1) + (x<<3) + c -'0';c = getchar();}if (!w) x = -x;
}
template <typename T>
void Write(T x) {if (x < 0) {putchar('-');x = -x;}if (x > 9) Write(x / 10);putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e3 + 10;
const int Mod = 998244353;
const int bas1 = 233333;
const int bas2 = 19260817;int pow1[N], pow2[N];
int n, m, x, y;
char s[N][N], c[N][N];
int sum[N][N], val;int add(int a, int b) {return (a += b) >= Mod ? a - Mod : a;
}int mul(int a, int b) {return 1ll * a * b % Mod;
}int sub(int a, int b) {return (a -= b) < 0 ? a + Mod : a;
}int fast_pow(int a, int b) {int res = 1;while (b) {if (b & 1) res = mul(res, a);b >>= 1;a = mul(a, a);}return res;
}void init() {pow1[0] = pow2[0] = 1;fu(i, 1, N - 1) pow1[i] = mul(bas1, pow1[i - 1]);fu(i, 1, N - 1) pow2[i] = mul(bas2, pow2[i - 1]);
}void getsum() {fu(i, 1, n)fu(j, 1, m)sum[i][j] = add(sub(add(sum[i][j - 1], sum[i - 1][j]), sum[i - 1][j - 1]), mul(s[i][j], mul(pow1[i], pow2[j])));val = 0;fu(i, 1, x)fu(j, 1, y) val = add(val, mul(c[i][j], mul(pow1[i], pow2[j])));
}void solve() {Read(n), Read(m);fu(i, 1, n) scanf("%s", s[i] + 1);Read(x), Read(y);fu(i, 1, x) scanf("%s", c[i] + 1);getsum();int ans = 0;fu(i, x, n)fu(j, y, m)if (sub(add(sum[i][j], sum[i - x][j - y]), add(sum[i][j - y], sum[i - x][j])) == mul(val, mul(pow1[i - x], pow2[j - y])))++ans;Write(ans), putchar('\n');
}int main() {
#ifdef dream_makerfreopen("input.txt", "r", stdin);
#endifint T; Read(T);init();while (T--) solve();return 0;
}

思路2:AC自动机

用AC自动机来考虑的话这题挺好的

虽然跑600ms

考虑一下把模式串分解变成x个长度是y的串

然后全部塞进AC自动机

然后考虑算出在\(n*m\)的矩阵中有哪些串在哪些位置出现过

这个东西跑一边就可以处理出来

如果有不好处理的细节你就想怎么暴力怎么来

然后我们考虑假如在\((i,j)\)这个位置匹配到了第k行

那么对于左上角在\((i-k,j)\)的矩阵显然是可以匹配第k行的

那么我们就记录一下每个节点是左上角的矩阵最多能匹配多少行就可以了


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
typedef pair<int, int> pi;
typedef long long ll;
typedef double db;
#define fi first
#define se second
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
template <typename T>
void Read(T &x) {bool w = 1;x = 0;char c = getchar();while (!isdigit(c) && c != '-') c = getchar();if (c == '-') w = 0, c = getchar();while (isdigit(c)) {x = (x<<1) + (x<<3) + c -'0';c = getchar();}if (!w) x = -x;
}
template <typename T>
void Write(T x) {if (x < 0) {putchar('-');x = -x;}if (x > 9) Write(x / 10);putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e3 + 10;
const int CHARSET_SIZE = 26;
struct Node {int ch[CHARSET_SIZE], fail;int id[110];Node() {}void clean() {fu(i, 0, CHARSET_SIZE - 1) ch[i] = 0;id[0] = fail = 0;}
} p[N * N];
int n, m, x, y, cnt;
int res[N][N];
char s[N][N], c[N][N];void init() {cnt = 1;p[0].clean(); p[1].clean();fu(i, 0, CHARSET_SIZE - 1) p[0].ch[i] = 1;
}void insert(char *c, int id) {int u = 1;fu(i, 1, y) {int tmp = c[i] - 'a';if (!p[u].ch[tmp])p[p[u].ch[tmp] = ++cnt].clean();u = p[u].ch[tmp];}p[u].id[++p[u].id[0]] = id;
}void build_fail() {static queue<int> q;q.push(1);while (q.size()) {int u = q.front(); q.pop();fu(i, 0, CHARSET_SIZE - 1) {int w = p[u].ch[i], v = p[u].fail;while (!p[v].ch[i]) v = p[v].fail;v = p[v].ch[i];if (w) {p[w].fail = v;q.push(w);} else p[u].ch[i] = v;}}
}void trans(char *c, int id) {int u = 1;fu(i, 1, m) {u = p[u].ch[c[i] - 'a'];fu(j, 1, p[u].id[0]) {if (id >= p[u].id[j])res[id - p[u].id[j] + 1][i]++;}}
}void solve() {init();Read(n), Read(m);fu(i, 1, n) scanf("%s", s[i] + 1);Read(x), Read(y);fu(i, 1, x) {scanf("%s", c[i] + 1);insert(c[i], i);}build_fail();fu(i, 1, n) fu(j, 1, m) res[i][j] = 0;fu(i, 1, n) trans(s[i], i);int ans = 0;fu(i, 1, n) fu(j, 1, m) if (res[i][j] == x) ++ans;Write(ans), putchar('\n');
}int main() {
#ifdef dream_makerfreopen("input.txt", "r", stdin);
#endifint T; Read(T);while (T--) solve();return 0;
}

转载于:https://www.cnblogs.com/dream-maker-yk/p/9906052.html

UVA11019 Matrix Matcher【hash傻逼题】【AC自动机好题】相关推荐

  1. UVa11019 Matrix Matcher(hash+kmp)

    二维字符串匹配问题,将二维模式x*y转换成1*y列的哈希数组.同时将二维文本串n*m转换成(n-x+1)*m列的哈希矩阵,前x行先计算哈希,后面的通过滚动计算哈希值.然后遍历(n-x+1)次,通过km ...

  2. HDU2896(AC自动机模版题)

    AC自动机模版题: 方法一:超时 #include<iostream> #include<algorithm> #include<cstring> #include ...

  3. 数单词 (AC自动机模板题)

    数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级, ...

  4. NYOJ 1085 数单词 (AC自动机模板题)

    数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 为了能够顺利通过英语四六级考试,现在大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中可以通过六级, ...

  5. [Bzoj3940] [AC自动机,USACO 2015 February Gold] Censor [AC自动机模板题]

    AC自动机模板题(膜jcvb代码) 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> ...

  6. Leetcode 500题AC的刷题总结(C与C++)

    文章目录 前引闲聊 500AC达成截图 + 力扣刷题每日频率 前引闲聊 哈哈 又到了我的闲聊时间了 与其这篇说是500题AC的总结 不如说是我的闲聊时间 我记得上一篇关于Leetcode AC记录 还 ...

  7. 一道叉姐的AC自动机鬼题

    题面描述丢失了... 给n个串模板串,然后再给你m个串,对于这m个串的每个串,问在[L,R]的模板串中,在多少个串中出现过; 这题的正解是对于后m个串建AC自动机,然后离线,在fail树上树链求并. ...

  8. HDU 2222 Keywords Search (AC自动机模板题)

    一组数据: 1 3 sss sss sss sss ans:3 #include <cstdio> #include <cstdlib> #include <vector ...

  9. HDU2222(AC自动机模版题)

    AC自动机是Trie树和KMP的结合物,但是其实KMP在这里体现了思想,而Trie树才是最重要的,要想学懂AC自动机,学习Trie树是必须的,这些是自己在学习AC自动机的个人看法,我也是在网上学习了大 ...

最新文章

  1. python中,time、calendar、datetime
  2. ubuntu18.04.4 没有声音
  3. kafka配置公网IP访问
  4. String Split 和 Join
  5. 重磅 | AI 圣经 PRML《模式识别与机器学习》官方开源了!
  6. boost::convert模块实现默认转换器的测试程序
  7. 基于Dapper的开源Lambda扩展,且支持分库分表自动生成实体
  8. CSS3 线性渐变背景的过渡效果
  9. 树莓派做一个dns缓存
  10. 针对ArcGIS Server 跨域问题的解释
  11. 12c rac 实例无法启动之磁盘组空间耗尽
  12. SL8100 3.6V~100V降压型大功率LED恒流驱动器
  13. Python基础之列表、元组、字典、集合
  14. RK3568平台开发系列讲解(环境篇)RK3568 SDK Linux编译服务器开发坏境搭建
  15. MCV模型流程图整理
  16. 第三方直播美颜SDK的美颜功能是怎么实现的?
  17. 男孩年级轻轻就猝死,看到他最后时刻做的事,我被警醒了(漫画)
  18. VS SDK更新问题(error MSB8036: 找不到 Windows SDK 版本10.0.14393.0)
  19. 叙事的变迁:从《街》到《428》
  20. 【全套完整版本】YOLOv3使用方法记录

热门文章

  1. java rector_Java IO的Reactor模式
  2. android实现双向绑定,Android使用DataBinding实现双向绑定(一)
  3. python 优先队列_示例讲解:python队列原理及实现方法与操作思路
  4. tiptop 编译运行_ERP(tiptop linux下主要命令)
  5. python逻辑判断_return逻辑判断表达式
  6. 系统学习机器学习之增强学习(四)--马尔可夫决策过程策略MC求解
  7. 人脸检测(十七)--Faceness-Net
  8. java.rmi.ConnectException: Connection refused to host:
  9. Kicad安装与配置_Windows
  10. 什么是服务的熔断降级