AcWing - 156 矩阵(二维哈希)
标签:set 链接 desc 过程 har color res get a*
题目链接:矩阵
题意:给定一个$m$行$n$列的$01$矩阵$($只包含数字$0$或$1$的矩阵$)$,再执行$q$次询问,每次询问给出一个$a$行$b$列的$01$矩阵,求该矩阵是否在原矩阵中出现过
思路:二维哈希,从矩阵的右下角为低位到矩阵的左上角为高位,先求出每一行的一维哈希值$h[i][j]$,在$a$行$b$列的$01$矩阵向下移动的过程中,先向下扩展成$a+1$行$b$列的$01$矩阵,再将最上面的一行减去,这样矩阵就会向下移动一格,设原来$a$行$b$列矩阵的哈希值为$t$,所以新矩阵的哈希值
$$res=t*p[b]+(h[i+1][j]-h[i+1][j-b]*p[b])-((h[i-a][j]-h[i-a][j-b]*p[b])*p[a*b])$$
用$set$存储每个子矩阵的哈希值,求出询问矩阵的哈希值,判断是否出现过
其他二维哈希的题目,令矩阵的右下角为低位、矩阵的左上角为高位,然后推一下公式即可。
#include
#include
#include
#include set>
using namespace std;
typedef unsigned long long ull;
const int N = 1010;
const int M = N * N;
const ull P = 131;
int n, m, a, b, k;
ull h[N][N], p[M];
ull Hash(ull f[], int l, int r)
{
return f[r] - f[l - 1] * p[r - l + 1];
}
int main()
{
scanf("%d%d%d%d", &n, &m, &a, &b);
p[0] = 1;
for (int i = 1; i )
p[i] = p[i - 1] * P;
for (int i = 1; i ) {
char s[N];
scanf("%s", s + 1);
for (int j = 1; j )
h[i][j] = h[i][j - 1] * P + s[j] - ‘0‘;
}
set st;
for (int i = b; i ) {
ull t = 0;
int l = i - b + 1, r = i;
for (int j = 1; j ) {
t = t * p[b] + Hash(h[j], l, r);
if (j > a) t -= Hash(h[j - a], l, r) * p[a * b];
if (j >= a) st.insert(t);
}
}
scanf("%d", &k);
while (k--) {
ull t = 0;
char s[N];
for (int i = 1; i ) {
scanf("%s", s + 1);
for (int j = 1; j )
t = t * P + s[j] - ‘0‘;
}
if (st.count(t)) printf("1\n");
else printf("0\n");
}
return 0;
}
AcWing - 156 矩阵(二维哈希)
标签:set 链接 desc 过程 har color res get a*
原文地址:https://www.cnblogs.com/zzzzzzy/p/12250473.html
评论