文章目录

  • 1. 题目信息
    • 1.1 题目链接
    • 1.2 题目大意
    • 1.3 解题思路
  • 2. 代码
    • 2.1 Time Limit Exceeded 代码
    • 2.2 Time Limit Exceeded 代码
    • 2.3 Time Limit Exceeded 代码

1. 题目信息

1.1 题目链接

http://poj.org/problem?id=3690

1.2 题目大意

给定大的矩阵(天空的样子),然后给定若干小矩阵(可能的天空的一角)
求有多少个小矩阵是从大矩阵里抠出来的(2D匹配)

1.3 解题思路

采用RK算法,求矩阵的哈希值,看哈希值是否一样,若一样,再比较一下看是否真的一样(防止哈希冲突)

2. 代码

2.1 Time Limit Exceeded 代码


计算的是整体矩阵的哈希值

/*** @description: poj3690 2维矩阵匹配* @author: michael ming* @date: 2019/6/25 19:47* @modified by: */
#include <iostream>
#include <math.h>
using namespace std;
int a[1001][1001];
int b[51][51];
typedef unsigned long long ull;
ull cal_hash_b(int r, int c, int b[][51])
{int i, j, k;ull value = 0;for (i = 0; i < r; ++i) //计算2d模式串的hash值value{for(j = 0, k = 1; j < c; ++j,++k)value += b[i][j]*pow(2.0,k);}return value;
}
ull cal_hash_a_child(int i0, int j0, int r, int c, int a[][1001])
{int i, j, k;ull hash_value = 0;for (i = i0; i < r; ++i) //计算2d子串的hash值value{for(j = j0, k = 1; j < c; ++j,++k)hash_value += a[i][j]*pow(2.0,k);}return hash_value;
}
bool same(int a[][1001], int b[][51], int i0, int j0, int mr, int mc)
{int x = i0, y = j0, i, j;for(i = 0; i < mr; ++i,++x){for(j = 0, y = j0; j < mc; ++j,++y)//记得写y=j0,换行后y复位{if(a[x][y] != b[i][j])return false;}}return true;
}
int str_RK_2d(int a[][1001], int nr, int nc, int b[][51], int mr, int mc)//s是主串,t是模式串
{int i, j;ull hash_val, value;value = cal_hash_b(mr,mc,b);//计算2d模式串哈希值for(i = 0; i < nr-mr+1; ++i)//行最多nr-mr+1次比较{for(j = 0; j < nc-mc+1; ++j)//列最多nc-mc+1次比较{hash_val = cal_hash_a_child(i,j,mr+i,mc+j,a);//计算2d子串哈希值if(hash_val == value && same(a,b,i,j,mr,mc)){//如果2d子串哈希值等于模式串的,且"真的"字符串匹配(避免冲突带来的假匹配)return 1;}}}return 0;
}
void creatMatrix_a(int a[][1001], int r, int c)
{int i, j;char ch;for(i = 0; i < r; ++i)for(j = 0; j < c; ++j){cin >> ch;if(ch == '*')a[i][j] = 1;elsea[i][j] = 0;}
}
void creatMatrix_b(int b[][51], int r, int c)
{int i, j;char ch;for(i = 0; i < r; ++i)for(j = 0; j < c; ++j){cin >> ch;if(ch == '*')b[i][j] = 1;elseb[i][j] = 0;}
}
int main()
{int N, M, T, P, Q, count, ID = 1;while(cin >> N >> M >> T >> P >> Q && N){count = 0;creatMatrix_a(a,N,M);while(T--){creatMatrix_b(b,P,Q);count += str_RK_2d(a,N,M,b,P,Q);}cout << "Case " << ID++ << ": " << count << endl;}return 0;
}

2.2 Time Limit Exceeded 代码

优化了哈希值的计算方式,采用错位乘以2的方式,2的k次幂提前算好(还试了改成位运算),都是超时

/*** @description: poj3690 2维矩阵匹配* @author: michael ming* @date: 2019/6/25 19:47* @modified by:*/
#include <iostream>
using namespace std;
typedef unsigned long long ull;
int a[1001][1001];
int b[51][51];
ull cal_hash_b(int r, int c, int b[][51])
{int i, j, k;ull value = 0;for (i = 0; i < r; ++i) //计算2d模式串的hash值value{for(j = 0, k = c-1; j < c; ++j,--k){value += b[i][j]<<k;}}return value;
}
ull cal_hash_a_child(int i0, int j0, int r, int c, int a[][1001])
{int i, j, k;ull hash_value = 0;for (i = i0; i < r; ++i) //计算2d子串的hash值value{for(j = j0, k = c-1; j < c; ++j,--k)hash_value += a[i][j]<<k;}return hash_value;
}
bool same(int a[][1001], int b[][51], int i0, int j0, int mr, int mc)
{int x = i0, y = j0, i, j;for(i = 0; i < mr; ++i,++x){for(j = 0, y = j0; j < mc; ++j,++y)//记得写y=j0,换行后y复位{if(a[x][y] != b[i][j])return false;}}return true;
}
int sum(int a[][1001], int i0, int j0, int mr)
{int sum = 0;for(int x = 0; x < mr; ++x,++i0)sum += a[i0][j0];return sum;
}
int str_RK_2d(int a[][1001], int nr, int nc, int b[][51], int mr, int mc)//s是主串,t是模式串
{int i, j;ull hash_val, value;value = cal_hash_b(mr,mc,b);//计算2d模式串哈希值for(i = 0; i < nr-mr+1; ++i)//行最多nr-mr+1次比较{for(j = 0; j < nc-mc+1; ++j)//列最多nc-mc+1次比较{if(j == 0)hash_val = cal_hash_a_child(i,j,mr+i,mc+j,a);//计算2d子串哈希值elsehash_val = ((hash_val-(sum(a,i,j,mr)<<(mc-1)))<<1) + sum(a,i,j+mc-1,mr);if(hash_val == value && same(a,b,i,j,mr,mc)){//如果2d子串哈希值等于模式串的,且"真的"字符串匹配(避免冲突带来的假匹配)return 1;}}}return 0;
}
void creatMatrix_a(int a[][1001], int r, int c)
{int i, j;char ch;for(i = 0; i < r; ++i)for(j = 0; j < c; ++j){cin >> ch;if(ch == '*')a[i][j] = 1;elsea[i][j] = 0;}
}
void creatMatrix_b(int b[][51], int r, int c)
{int i, j;char ch;for(i = 0; i < r; ++i)for(j = 0; j < c; ++j){cin >> ch;if(ch == '*')b[i][j] = 1;elseb[i][j] = 0;}
}
int main()
{int N, M, T, P, Q, count, ID = 1;while(cin >> N >> M >> T >> P >> Q && N){count = 0;creatMatrix_a(a,N,M);while(T--){creatMatrix_b(b,P,Q);count += str_RK_2d(a,N,M,b,P,Q);}cout << "Case " << ID++ << ": " << count << endl;}return 0;
}

2.3 Time Limit Exceeded 代码

改为计算每行的哈希值,把大矩阵的所有小矩阵的宽度的每行哈希值算出来,后面开始逐行比较,有不符合的,跳出,寻找下一个,还是超时

/*** @description: poj3690 2维矩阵匹配* @author: michael ming* @date: 2019/6/25 19:47* @modified by:*/
#include <time.h>
#include <stdio.h>
typedef unsigned long long ull;
int a[1001][1001];
int b[51][51];
ull hash_b[51];//存放每行的哈希值,每行相当于一个2进制数
ull hash_a[1001][1001];//存放主串子串的哈希值void cal_hash_b(int r, int c, int b[][51])
{int i, j, k;ull value;for (i = 0; i < r; ++i) //计算2d模式串的hash值value{value = 0;for(j = 0, k = c-1; j < c; ++j,--k){value += b[i][j]<<k;}hash_b[i] = value;}return;
}
void cal_hash_a_child(int N, int M, int a[][1001], int P, int Q)
{int i, j, k, x;ull hash_value;for (i = 0; i < N; ++i) //计算2d子串的每行的hash值{for(j = 0; j < M-Q+1; ++j){if(j == 0){hash_value = 0;for(x = j, k = Q-1; x < j+Q && k >= 0; ++x,--k)hash_value += a[i][x]<<k;}elsehash_value = ((hash_a[i][j-1]-(a[i][j-1]<<(Q-1)))<<1)+a[i][j+Q-1];hash_a[i][j] = hash_value;}}
}int str_RK_2d(int a[][1001], int N, int M, int b[][51], int P, int Q)//s是主串,t是模式串
{int i, j, k, x;bool flag = false;cal_hash_b(P,Q,b);//计算2d模式串每行哈希值for(j = 0; j < M-Q+1; ++j)//列最多nc-mc+1次比较,分别比较每行,列先固定{for(i = 0; i < N-P+1; ++i){//行最多nr-mr+1次比较for(x = i, k = 0; x < i+P && k < P; ++x,++k){//一组比较P行if(hash_a[x][j] == hash_b[k])//比较子串哈希值flag = true;else{flag = false;break;}}if(flag == true)return 1;}}return 0;
}
void creatMatrix_a(int a[][1001], int r, int c)
{int i, j;char ch;for(i = 0; i < r; ++i)for(j = 0; j < c; ++j){ch = getchar();while(ch == ' '||ch == '\n')ch = getchar();if(ch == '*')a[i][j] = 1;elsea[i][j] = 0;}
}
void creatMatrix_b(int b[][51], int r, int c)
{int i, j;char ch;for(i = 0; i < r; ++i)for(j = 0; j < c; ++j){ch = getchar();while(ch == ' '||ch == '\n')ch = getchar();if(ch == '*')b[i][j] = 1;elseb[i][j] = 0;}
}
int main()
{//    clock_t start, finish;
//    start = clock();int N, M, T, P, Q, count, ID = 1;while((scanf("%d%d%d%d%d",&N,&M,&T,&P,&Q)!=EOF) && N){count = 0;creatMatrix_a(a,N,M);cal_hash_a_child(N,M,a,P,Q);while(T--){creatMatrix_b(b,P,Q);count += str_RK_2d(a,N,M,b,P,Q);}printf("Case %d: %d\n",ID++,count);}
//    finish = clock();
//    cout << "takes "<< finish-start << " ms." << endl;return 0;
}

POJ 3690 找星座(2D匹配)(未解答)相关推荐

  1. 【408计算机考研】|【2018统考真题-41】| 给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数

    目录 一.题目 二.解答 三.测试数据 一.题目   给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算 法,找出数组中未出现的最小正整数.例如,数组{-5, 3, 2, 3}中未 ...

  2. 给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。

    笔者初涉<算法设计与分析>这门专业课,在做一些算法设计题的过程中遇到一些小感悟,特此记录和大家分享. 下面直接给出算法题目: 给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高 ...

  3. 找不到outgoing_Xshell显示找不到匹配的outgoing encryption算法怎么办

    由用户反应在使用xshell和xftp连接debian 7时出现找不到匹配的outgoing encryption算法的错误提示,本集小编整理了一份解决方法,大家可以试试看. 问题阐述: 在用xshe ...

  4. 找不到outgoing_转:Xshell显示找不到匹配的outgoing encryption算法怎么办

    由用户反应在使用xshell和xftp连接debian 7时出现找不到匹配的outgoing encryption算法的错误提示,本集小编整理了一份解决方法,大家可以试试看. 问题阐述: 在用xshe ...

  5. 找不到匹配的outgoing encryption 算法

    xshell连接服务器报"找不到匹配的outgoing encryption算法" 解决方法打开会话的属性(在会话上右键 - 属性 - SSH - 安全性)选中aes192-ctr ...

  6. 找不到匹配的outgoing encryption算法

    找不到匹配的outgoing encryption算法 原因:是ssh登录本地终端缓存了相关的安全确认信息,远端的ssh服务升级后,其对应的加密算法均作了升级.修改,而本地的缓存安全信息并无更新,导致 ...

  7. 解决用Xshell工具通过ssh登陆linux操作系统提示找不到匹配的host key算法问题

    前几天升级了两台linux服务器的openssh,当时测试两台服务器通过xshell登陆都是正常的.今天通过xshell登陆报找不到匹配的host key算法,如下图所示: 试过https://blo ...

  8. POJ 1276 ATM凑钱(动态规划)(未解答)

    文章目录 1. 题目 1.1 题目链接 1.2 题目大意 1.3 解题思路 2. 代码 2.1 Accepted代码 1. 题目 1.1 题目链接 http://poj.org/problem?id= ...

  9. vs2010 QT: release时 提示“无法找到.exe的调试信息 或者调试信息不匹配 未使用调试信息生成二进制文,是否继续调试”的解决方案

    vs2010+ qt 新建一个application程序,DEBUG编译的时候没有问题,但是改成release编译的时候会出来一个界面,显示: "无法找到xxx.exe调试信息,或者调试信息 ...

最新文章

  1. php常用20函数,PHP常用函数
  2. Windows下配置scrapy需要MVC的14.0版本(转载)
  3. 谈谈几个 Spring Cloud 常见面试题及答案
  4. 在VMware上快速安装win 2003
  5. 使用SSM开发一个校友联络的平台系统
  6. Android Resource介绍和使用
  7. 适用于ATI卡的GPU计算MD5的小程序源码,基于AMD APP SDK开发
  8. struct linger
  9. 查python答案的软件-中国大学MOOC的APP慕课用Python玩转数据答案查题公众号
  10. XP计算机调整对比度,Win7系统调节显示器屏幕对比度的两种方法【图文】
  11. Linux抓包工具tcpdump例子
  12. codeforce438D The Child and Sequence
  13. Sql Server 学习2
  14. 12864与24C04的原理和使用方法——以电子密码锁为例(上篇)
  15. centos 下 docker 的 安装与使用 (一)
  16. windows快速清理垃圾文件bat
  17. EISeg——应用于语义分割的自动标注软件
  18. 实现计算机联网的最大好处是,职.称计算机考试多项选择题考试卷模拟考试题...
  19. 计算机硬件未来发展前景,计算机硬件发展现状
  20. 中国呼吸介入领导者堃博医疗在港交所挂牌上市;勃林格殷格翰收购Abexxa Biologics | 医药健闻...

热门文章

  1. 计算机等级考试2010,2010年全国计算机等级考试相关政策
  2. Linux进程全解6——进程的诞生和消亡
  3. 本地连接Linux工具
  4. 【洛谷 2661】信息传递
  5. Java IO/NIO教程
  6. CI Weekly #11 | 微服务场景下的自动化测试与持续部署
  7. HDU 4117 GRE Words
  8. SequoiaDB 系列之六 :源码分析之coord节点
  9. 微信开发学习日记(一):快速阅读5本书,掌握整体背景
  10. 说说 JavaScript 计时器的工作原理