UVA-11019 二维哈希算法
题意:
就是给你AB两个字符矩阵,问你B矩阵在A矩阵中的出现次数。
题解: 参考链接:https://blog.csdn.net/qq_38891827/java/article/details/80723483
我们可以进行二维hash,其实就是把n个横向串连在一起hash。
注意判相等的时候,我们不断进行尺取+hash,尺取的过程,我们删除当前第一行的hash值加上最后一行的hash值,删除第一行的hash值直接删去就可以
例如
AAAAAA
BBBBBB
CCCCCC
我们删去第一行的hash值 相当于把矩阵变成了
000000
BBBBBB
CCCCCC
此时我们再添加最后一行
000000
BBBBBB
CCCCCC
DDDDDD
如果这时候的B矩阵是
BBBBBB
CCCCCC
DDDDDD
这两个矩阵的hash值不同的,为了处理这种情况,我们把B矩阵相应的添加前几行
变成
000000
BBBBBB
CCCCCC
DDDDDD
这样再去匹配就可以了。
以上就是二维hash大概的处理方法(是我自己想的做法,如果有其他好的尺取方法欢迎指教
掌握了这个做法,我们就可以枚举矩阵的左上角,然后对于当前列数的矩阵从上向下进行尺取,hash判断就可以了。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<sstream> #include<map> using namespace std; const int maxn=1e3+5; const int N=1e6+5; const int blo=31; typedef unsigned long long ull; ull hash_[maxn][maxn],xp[N]; char str[maxn][maxn],str2[maxn][maxn]; void init() { xp[0]=1; for(int i=1; i<N; ++i) { xp[i]=xp[i-1]*blo; } } ull Get_hash(int i,int j,int l) { return hash_[i][j]-hash_[i][j+l]*xp[l]; } int main() { init(); int t; scanf("%d",&t); while(t--) { int n1,n2,m1,m2,ans=0; scanf("%d%d",&n1,&m1); for(int i=0; i<n1; ++i) scanf("%s",str[i]); scanf("%d%d",&n2,&m2); for(int i=0; i<n2; ++i) scanf("%s",str2[i]); for(int i=0; i<n1; ++i) { hash_[i][m1]=0; for(int j=m1-1; j>=0; j--) { hash_[i][j]=hash_[i][j+1]*blo+(str[i][j]-'A'+1); } } ull tmp=0; for(int i=n2-1; i>=0; --i) { for(int j=m2-1; j>=0; j--) { tmp=tmp*blo+(str2[i][j]-'A'+1); } } for(int i=0; i<m1-m2+1; ++i) { ull tmp1=tmp,tmp2=0; for(int j=n2-1; j>=0; j--) { tmp2=tmp2*xp[m2]+Get_hash(j,i,m2); } if(tmp1==tmp2) ans++; for(int j=n2; j<n1; ++j) { tmp2-=Get_hash(j-n2,i,m2)*xp[(j-n2)*m2]; tmp2+=Get_hash(j,i,m2)*xp[j*m2]; tmp1=tmp1*xp[m2]; if(tmp2==tmp1) ans++; } } printf("%d\n",ans); } return 0; }