咕题存档
对Catherine这种蒟蒻来说还是太难了
7-7 寻宝游戏
题目描述
小 r 最近在抖音上看到一个叫做《疯狂大寻宝》的小游戏,如图所示:

由于实在是太难了,于是小 r 决定使用代码去找到所有的物品,我们将地图通过抽象得到一个二维的字符数组,其构成一个边长为 的正方形,每个物品也是一个二维的字符数组,你需要做的是对于每一种物品找到它出现的位置。
简单来说,就是给定一个矩形二维数组,查询其他正方形二维数组在这个二维数组中出现的位置。
输入格式
第一行输入三个数 ,表示地图的行数、列数以及物品数。
接下来 行每行 个字符,均为 ACSII 码在 33-126 的字符,即非空字符。
接下来输入 组数据,
每组数据先输入一行两个数,表示该物品抽象成的图案的边长;
接下来 行每行 个字符,均为 ACSII 码在 33-126 的字符 ,即非空字符。
输出格式
输出 组数据,每组数据第一行输出该物品出现的个数 。
接下来 行每行输出两个数,表示该物品出现的位置左上角的坐标,中间用空格隔开,要求先按照行号升序排列,再按照列号升序来排列。(坐标从 点开始)
数据范围和约定
。
输入输出样例
输入样例 1
5 5 3
adhjb
sdqbh
bhkbh
bhjbh
nqbdw
2
hj
qb
1
b
2
bh
bh
输出样例 1
2
1 3
4 2
7
1 5
2 4
3 1
3 4
4 1
4 4
5 3
3
2 4
3 1
3 4
代码长度限制
16 KB
时间限制
2000 ms
内存限制
512 MB
栈限制
8192 KB
以下是——终于抄对了的一版
ACcode(∑)
//先交一版存档吧
//不知道怎么抄都能抄错
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 10;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch^48);
ch = getchar();
}
return x * f;
}
ull h[maxn][15], b[maxn][15];
const int pi = 131;
string s[maxn], p[maxn];
int l2[maxn], n, m, q;
struct node {int a, b;};
vector<node> ans;
int main()
{
//这个嘛,鹤一下二维Hash吧,场上都没做出来
for(int i=2; i<=1e5; i++) l2[i] = l2[i>>1] + 1;
//i是2的几次方
scanf("%d%d%d", &n, &m, &q);
for(int i=0; i<n; i++) cin >> s[i];
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
h[i*m+j][0] = s[i][j];//把二维数组压扁了
}
}
ull ni = pi;
//n*m<=1e5, a*a<=1e5
for(int k=1; k<14; k++)//2^14 = 16834
{
for(int i=0; i<=n-(1<<k); i++)
{
for(int j=0; j<=m-(1<<k); j++)//确保长度在范围内
{
//倍增吗?以i*m+j...为起点的长度为2^(k-1)的序列hash
//只不过使用的“进制”却不是2
h[i*m+j][k] = h[i*m+j][k-1]*ni+h[i*m+j+(1<<k-1)][k-1];
/*
横向
h[i][j][k] = h[i][j][k-1]*ni+h[i][j+(1<<k-1)][k-1];
纵向
h[i][j][k] = h[i][j][k]*ni+h[i+(1<<k-1)][j][k-1];
横向+纵向
h[i][j][k] = h[i][j][k]*ni+h[i+(1<<k-1)][j+(1<<k-1)][k-1];
*/
h[i*m+j][k] = h[i*m+j][k]*ni+h[i*m+j+(1<<k-1)*m][k-1];
h[i*m+j][k] = h[i*m+j][k]*ni+h[i*m+j+(1<<k-1)*m+(1<<k-1)][k-1];
}
}
ni = ni * ni * ni * ni;
}
for(int ht=1; ht<=q; ht++)
{
int a; scanf("%d", &a);
for(int i=0; i<a; i++) cin >> p[i];
int l = l2[a];
for(int i=0; i<a; i++)
{
for(int j=0; j<a; j++)
{
b[i*a+j][0] = p[i][j];
}
}
ni = pi;
for(int k=1; k<=l2[a]; k++)
{
for(int i=0; i<=a-(1<<k); i++)
{
for(int j=0; j<=a-(1<<k); j++)
{
b[i*a+j][k] = b[i*a+j][k-1]*ni+b[i*a+j+(1<<k-1)][k-1];
b[i*a+j][k] = b[i*a+j][k]*ni+b[i*a+j+(1<<k-1)*a][k-1];
b[i*a+j][k] = b[i*a+j][k]*ni+b[i*a+j+(1<<k-1)*a+(1<<k-1)][k-1];
}
}
ni = ni * ni * ni * ni;
}
ans.clear();
int c = a - (1 << l);
for(int i=0; i<=n-a; i++)
{
for(int j=0; j<=m-a; j++)
{
if(h[i*m+j][l] == b[0][l] && h[(i+c)*m+j][l] == b[c*a][l] &&
h[i*m+j+c][l] == b[c][l] && h[(i+c)*m+j+c][l] == b[c*a+c][l])
ans.push_back({i+1, j+1});
}
}
printf("%d\n", ans.size());
for(auto [i, j] : ans) printf("%d %d\n", i, j);
}
return 0;
}
时光花火,水月星辰

浙公网安备 33010602011771号