您的位置:首页 > 其它

POJ 3690 Constellations(二进制压位+KMP)

2018-03-06 21:13 459 查看

题目链接

这儿~~

题解

这道题一看就知道是个二维hash,然而蒟蒻我并不会,于是想了另外一种水法:KMP

首先对小矩阵的每一列压位变成一个long long。然后小矩阵就变成了一个长度为q的数组。对大矩阵做同样的操作,每列p位压成一个数(可重叠),然后大矩阵就变成了n-p+1行m列的矩阵。

对矩阵的每一行与数组做KMP即可。

时间复杂度O(跑得过)。

ps:数据好水,刚AC的程序被我hack掉了。。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <cstdlib>
#define maxn 1010

using namespace std;

typedef long long LL;

int n, m, p, q, T, ans, Case;

char M1[maxn][maxn], M2[maxn][maxn];
LL D1[maxn][maxn], D2[maxn];
int nxt[maxn];

bool KMP(int x){

nxt[0] = nxt[1] = 0;
int k = 0;

for(int i = 2; i <= q; i++){
while(k && D2[k] != D2[i-1])  k = nxt[k];
if(D2[k] == D
4000
2[i-1])  k ++;
nxt[i] = k;
}

k = 0;

for(int i = 1; i <= m; i++){
while(k && D2[k] != D1[x][i-1])  k = nxt[k];
if(D2[k] == D1[x][i-1])  k ++;
if(k == q)  return true;
}
return false;
}

int main(){

for(;;){
scanf("%d%d%d%d%d", &n, &m, &T, &p, &q);

if(!n && !m && !T && !p && !q)  break;

ans = 0;

for(int i = 1; i <= n; i++)
scanf("%s", M1[i]);

for(int j = 0; j < m; j++){
D1[1][j] = 0LL;
for(int i = 1, t = 0; i <= p; i++, t++)
if(M1[i][j] == '*')  D1[1][j] += (1LL << t);

for(int i = p+1; i <= n; i++){
D1[i-p+1][j] = (D1[i-p][j] >> 1LL);
if(M1[i][j] == '*')  D1[i-p+1][j] += (1LL << (p-1));
}
}

while(T --){
for(int i = 1; i <= p; i++)
scanf("%s", M2[i]);

for(int j = 0; j < q; j++){
D2[j] = 0LL;
for(int i = 1, t = 0; i <= p; i++, t++)
if(M2[i][j] == '*')  D2[j] += (1LL << t);
}

for(int i = 1; i <= n-p+1; i++)
if(KMP(i)){
ans ++;
break;
}
}

printf("Case %d: %d\n", ++Case, ans);
}

return 0;
}


我对命运嗤之以鼻,命运赐我以葬礼。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: