您的位置:首页 > 其它

POJ 3690 Constellations 哈希表 矩阵匹配

2017-08-26 15:04 267 查看

题目大意

给出一个n * m的矩阵,矩阵中只有一些*或者0

n <= 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: 1

Case 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: