题目大意:给一个图和几个子图,判断有多少种子图在原图出现过。
——————————————————————
二维哈希即可,操作看代码,我觉得蛮好看的。
注意这题恶心的时限。
pow预处理能少时间,读入字符用getchar不然会TLE。
用multiset查找然后再一个个erase即可,这样set前后size的差值即是答案。
#include#include #include #include #include #include using namespace std;typedef unsigned long long ll;const int N=1001;const int M=1001;const int P=51;const int Q=51;const ll b=2;const ll w=1e8+7;ll ha0[N][M];ll ha1[P][Q];ll qpow[2][P];inline ll tn(char ch){ if(ch=='0')return 0; return 1;}void init(){ qpow[0][0]=qpow[1][0]=1; for(int i=1;i >n>>m>>t>>p>>q){ if(n+m+t+p+q==0)break; multiset app; casenum++; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ char ch=getchar(); while(ch==' '||ch=='\n')ch=getchar(); ha0[i][j]=ha0[i][j-1]*b+tn(ch); } } for(int j=1;j<=m;j++){ for(int i=1;i<=n;i++){ ha0[i][j]+=ha0[i-1][j]*w; } } for(int k=1;k<=t;k++){ for(int i=1;i<=p;i++){ for(int j=1;j<=q;j++){ char ch=getchar(); while(ch==' '||ch=='\n')ch=getchar(); ha1[i][j]=ha1[i][j-1]*b+tn(ch); } } for(int j=1;j<=q;j++){ for(int i=1;i<=p;i++){ ha1[i][j]+=ha1[i-1][j]*w; } } app.insert(ha1[p][q]); } for(int i=p;i<=n;i++){ for(int j=q;j<=m;j++){ int si=i-p,sj=j-q; app.erase(ha0[i][j]-ha0[si][j]*qpow[1][p]-ha0[i][sj]*qpow[0][q]+ha0[si][sj]*qpow[1][p]*qpow[0][q]); } } printf("Case %d: %d\n",casenum,t-(int)app.size()); } return 0;}