Codeforces Contest 958 problem A2 Death Stars (medium) —— 字符串hash求两个矩阵是否有相同部分

This way

题意:

给你一个nm的字符矩阵,一个mn的字符矩阵,问你他们相同的m*m的字符矩阵所在第一个矩阵的行数和第二个矩阵的列数。

题解:

我们把第一个字符矩阵当成一行处理,然后对于第二个字符矩阵,我们预处理所有的mm块将哈希值保存到左上角,如图:
在这里插入图片描述
注意要用双哈希,但是脸黑也可能过不去。。
之后我们就枚举第一个字符矩阵的起始位置,再枚举第二个字符矩阵的起始位置即可,时间复杂度n
n,但是预处理时间复杂度nmm,也有更优的预处理方法,但没必要
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pa pair<ll,ll>
const ll mod=1e9+7,p1=37,p2=23;
char s1[400005],s2[205][2005];
ll sump1[400005],sump2[400005];
pa hash2[2005],hash1[400005];
pa gethash1(int sta,int fin)
{
    ll h1=(hash1[fin].first-hash1[sta].first*sump1[fin-sta]%mod+mod)%mod;
    ll h2=(hash1[fin].second-hash1[sta].second*sump2[fin-sta]%mod+mod)%mod;
    return (pa){h1,h2};
}
int n,m;
void Hash()
{
    ll ret1,ret2;
    sump1[0]=sump2[0]=1;
    for(int i=1;i<=n*m;i++)
    {
        hash1[i].first=(hash1[i-1].first*p1+(ll)s1[i])%mod;
        hash1[i].second=(hash1[i-1].second*p2+(ll)s1[i])%mod;
        sump1[i]=sump1[i-1]*p1%mod,sump2[i]=sump2[i-1]*p2%mod;
    }
    for(int i=1;i<=n-m+1;i++)
    {
        ret1=ret2=0;
        for(int j=1;j<=m;j++)
        {
            for(int k=i;k<=m+i-1;k++)
            {
                ret1=(ret1*p1+(ll)s2[j][k])%mod;
                ret2=(ret2*p2+(ll)s2[j][k])%mod;
            }
        }
        hash2[i]=(pa){ret1,ret2};
    }
}
int main()
{

    scanf("%d%d",&n,&m);
    getchar();
    for(int i=1;i<=n*m;i++)
    {
        scanf("%c",s1+i);
        if(i%m==0)
            getchar();
    }
    for(int i=1;i<=m;i++)
        scanf("%s",s2[i]+1);
    Hash();
    //if(n==2000&&m==1)
        //printf("%s",s2[1]);
    for(int i=1;i<=n*m-m*m+1;i+=m)
    {
        pa h1=gethash1(i-1,i+m*m-1);
        for(int j=1;j<=n-m+1;j++)
            if(h1==hash2[j])
                return 0*printf("%d %d\n",(i+m-1)/m,j);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值