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

    xiaoxiao2025-04-18  6

    This way

    题意:

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

    题解:

    我们把第一个字符矩阵当成一行处理,然后对于第二个字符矩阵,我们预处理所有的mm块将哈希值保存到左上角,如图: 注意要用双哈希,但是脸黑也可能过不去。。 之后我们就枚举第一个字符矩阵的起始位置,再枚举第二个字符矩阵的起始位置即可,时间复杂度nn,但是预处理时间复杂度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); } }
    最新回复(0)