POJ 3690 Constellations 哈希表 矩阵匹配
2017-08-26 15:04
267 查看
题目大意
给出一个n * m的矩阵,矩阵中只有一些*或者0n <= 1000, m <= 1000
然后有t (t <= 100)个询问,每次询问给出一个p * q的矩阵
p,q是提前固定的数值。
问这些询问中能是大矩阵的子矩阵的有几个
Sample Input
3 3 2 2 2*00
0**
*00
**
00
*0
**
3 3 2 2 2
*00
0**
*00
**
00
*0
0*
0 0 0 0 0
Sample Output
Case 1: 1Case 2: 2
解题思路
因为小矩阵的长宽都给定了,所以可以直接O(n2)预处理出大矩阵中每个p*q的小矩阵的哈希值(最多n*m个)放入哈希表中,再用给的小矩阵查询即可。预处理时先用pre[i][j]处理出第i行前j的字符的哈希值,再算出每个位置开始q个字符的哈希值,然后用sum[i][j]处理1至i行从第j个字符开始q个字符的哈希值,也就是前缀和,最后用两个前缀和相减(sum[i][j]-sum[i][j-p]*pow[p*c])即为以第i-r+1行第j个字符为左上角的p*q的矩阵的哈希值了。
注意哈希表模数要取6位以上的素数(999997,233333),不然要超时,亲身经历,wu~~~~
时间复杂度O(n2)
这里写代码片 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<queue> #define ll unsigned long long using namespace std; int getint() { int i=0 ,f=1;char c; for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int N=1005,p=3,H=999997; char s ; int T,n,m,q,r,c,ans; ll cf[2505],pre ,sum ,val[N*N]; int tot,hsh[H+5],nxt[N*N]; void insert(ll x) { int y=x%H; for(int v=hsh[y];v;v=nxt[v]) if(val[v]==x)return; nxt[++tot]=hsh[y],hsh[y]=tot,val[tot]=x; return; } void find(ll x) { int y=x%H; for(int v=hsh[y];v;v=nxt[v]) if(val[v]==x) { ans++; return; } return; } void Init() { memset(hsh,0,sizeof(hsh)); memset(pre,0,sizeof(pre)); memset(sum,0,sizeof(sum)); memset(cf,0,sizeof(cf)); ans=tot=0; ll x; m=getint(),q=getint(),r=getint(),c=getint(); cf[0]=1; for(int i=1;i<=r*c;i++)cf[i]=cf[i-1]*p; for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=m;j++) { if(s[j]=='0')pre[i][j]=pre[i][j-1]*p; else pre[i][j]=pre[i][j-1]*p+1; } } for(int i=1;i<=n;i++) { for(int j=1;j<=m-c+1;j++) { sum[i][j]=pre[i][j+c-1]-pre[i][j-1]*cf[c]; sum[i][j]=sum[i-1][j]*cf[c]+sum[i][j]; } } for(int i=r;i<=n;i++) for(int j=1;j<=m-c+1;j++) { x=sum[i][j]-sum[i-r][j]*cf[r*c]; insert(x); } } void solve() { ll x=0; for(int i=1;i<=r;i++) { scanf("%s",s+1); for(int j=1;j<=c;j++) { if(s[j]=='0')x=x*p; else x=x*p+1; } } find(x); } int main() { //freopen("lx.in","r",stdin); while(n=getint()) { if(n==0)break; Init(); while(q--) solve(); cout<<"Case "<<++T<<": "<<ans<<'\n'; } return 0; }
相关文章推荐
- POJ 3690(Constellations-矩阵hash)
- [poj] 3690 Constellations || 矩阵hash
- poj 3690 Constellations 二维滚动哈希匹配
- poj 3690 Constellations 矩阵的hash
- poj 3690 字符矩阵匹配----HASH算法
- poj 3690 Constellations
- poj 3041 Asteroids(二分图 *【矩阵实现】【最小点覆盖==最大匹配数】)
- poj3690 Constellations
- POJ 3690 Constellations (哈希)
- POJ 3690 Constellations + Gym - 100783J The Big Painting 二维字符串hash
- poj 2185 Milking Grid(最小矩阵覆盖,二维 kmp 匹配)
- POJ 3690 Constellations(二进制压位+KMP)
- POJ 3690 Constellations 简单hash
- POJ 3690 Constellations 笔记
- POJ 1469 COURSES(二分图最大匹配) (矩阵和邻接表的模板题)
- POJ3690 Constellations 【KMP】
- poj 1469 COURSES(简单)(二部图匹配 DFS)
- 【矩阵快速幂】ZOJ 3690 Choosing number
- poj 1274 二分图 最大匹配
- POJ 3318 Matrix Multiplication(矩阵乘法)