咕题存档

 对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;
}

 

posted @ 2025-07-07 11:54  Catherine_leah  阅读(36)  评论(0)    收藏  举报
/* */