恩,其实大家都没有报零,反正我是蒟蒻

为了纪念我第一次打过哈希,特此写一篇题解

题目描述

从前有一个的小矩阵,矩阵的每个元素是一个字母(区分大小写),突然有一天它发生了

变异,覆盖了整个二维空间,即不停自我复制产生相同的矩阵然后无隙放置。现在二维空间

已经被它占领了,但你只被告知了大小为R*C 空间的内容(可能包含不完整的原矩阵),为了

将它恢复原状,你需要找到满足条件的面积最小的原矩阵。

奇怪的是,同时有 T 个二维空间发生了变异,你需要尽快解决这些变异。

输入格式

第一行为一个整数T,表示二维空间数目。

接下来T 组数据。每组数据第一行包含两个数 R,C,表示你被告知的空间大小;接下

来 R 行,每行包含 C 个字母,表示你被告知的空间内容。

输出格式

对于每一组数据输出一行,每行只包含一个数,表示最小的原矩阵面积。

样例输入

2

2 5

ABABA

ABABA

2 8

ABCDEFAB

AAAABAAA

样例输出

2

12

数据范围与约定

对于前20%的数据 R<=20,C<=20;

对于前40%的数据R<=400,C<=100;

对于100%的数据R<=5000 ,C<=100,T<=50。

前20%的数据:大暴力,枚举原矩阵的左上角和右下角,暴力判断是否满足为原矩阵。

前40%的数据:考虑到一个性质,我们一定可以将原矩阵挪到给定矩阵的左上角考虑(循环

节的性质),那么就只用枚举原矩阵的右下角,用二维hash 可以判断两个矩形是否相等来优

化暴力,这样就能拿到40 分。

前100%的数据:

做法1:hash 暴力求出每一行可能的循环节长度,取公共的最小循环节长度即可,列同

理。将两次求得的最小循环节长度相乘即为答案。较慢,可能会超时。

做法 2:将每一行hash 为一个数,对得到的新数组直接跑KMP 求最小循环节长度,列

同理。将两次求得的最小循环节长度相乘即为答案。这就是std 做法。

一直觉得哈希是一个玄学玩意,特别怕冲突情况。但是如果哈希函数写得好,再加上人品不错,应该是可以水过去的

通常BKDRHash是比较优的

unsigned int BKDRHash(char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0; while (*str)
{
hash = hash * seed + (*str++);
} return (hash & 0x7FFFFFFF);
}

代码(其实就是存一个代码)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ui unsigned int
using namespace std; const int N=5000+5; int r,c,nxt[N];
ui H[N];
char s[N][N]; ui hash_x(int x){
ui seed=131;
ui hash=0;
for(int i=0;i<c;i++)
hash=hash*seed+s[x][i];
return hash;
}
ui hash_y(int x){
ui seed=131;
ui hash=0;
for(int i=0;i<r;i++)
hash=hash*seed+s[i][x];
return hash;
}
int getkmp_x(){
memset(nxt,0,sizeof(nxt));
int i=0,j=-1;
nxt[0]=-1;
while(i<r){
if(j==-1||H[i]==H[j]){
i++,j++;
nxt[i]=j;
}
else j=nxt[j];
}
return r-nxt[r];
}
int getkmp_y(){
memset(nxt,0,sizeof(nxt));
int i=0,j=-1;
nxt[0]=-1;
while(i<c){
if(j==-1||H[i]==H[j]){
i++,j++;
nxt[i]=j;
}
else j=nxt[j];
}
return c-nxt[c];
}
int getans_x(){
memset(H,0,sizeof(H));
for(int i=0;i<r;i++)
H[i]=hash_x(i);
return getkmp_x();
}
int getans_y(){
memset(H,0,sizeof(H));
for(int i=0;i<c;i++)
H[i]=hash_y(i);
return getkmp_y();
}
void solve(){
scanf("%d%d",&r,&c);
for(int i=0;i<r;i++)
scanf("%s",s[i]);
int x,y;
x=getans_x();
y=getans_y();
printf("%d\n",x*y);
}
int main(){
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}

7.26机房报零赛——无尽的矩阵【kmp+hash】的更多相关文章

  1. android stdio 编译项目报Error:Failed to find target with hash string 'android-24

    android stdio 编译项目报Error:Failed to find target with hash string 'android-24 查看已有的SDK 设置项目的sdk为 25 an ...

  2. 2016 10 26考试 NOIP模拟赛 杂题

    Time 7:50 AM -> 11:15 AM 感觉今天考完后,我的内心是崩溃的 试题 考试包 T1: 首先看起来是个贪心,然而,然而,看到那个100%数据为n <= 2000整个人就虚 ...

  3. 26、从零写UVC驱动之分析描述符

    指令:lsusb 可以查看usb设备的描述符信息,当然lsusb指令要带一些参数 一个usb设备有多个config配置+设备描述符,一个config有多个接口和association.config描述 ...

  4. NOIP2016报零记

    其实,NOIP2016已经于10天之前就结束了,但是由于种种原因,没有写总结. 现在就来填上这个坑吧. DAY1: T1:一道简(kun)单(nan)的模拟,虽然ac,但是考试的时候总觉得怪怪的.并且 ...

  5. 4.26 省选模拟赛 T3 状压dp 差分求答案

    LINK:T3 比较好的题目 考试的时候被毒瘤的T2给搞的心态爆炸 这道题连正解的思路都没有想到. 一看到题求删除点的最少个 可以使得不连通. 瞬间想到最小割 发现对于10分直接跑最小割即可. 不过想 ...

  6. 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 Coin 概率+矩阵快速幂

    题目链接: https://nanti.jisuanke.com/t/17115 题意: 询问硬币K次,正面朝上次数为偶数. 思路: dp[i][0] = 下* dp[i-1][0] + 上*dp[i ...

  7. HDU 5015 233 Matrix(网络赛1009) 矩阵快速幂

    先贴四份矩阵快速幂的模板:http://www.cnblogs.com/shangyu/p/3620803.html http://www.cppblog.com/acronix/archive/20 ...

  8. [机房练习赛7.26] YYR字符串

    1  无尽的矩阵(matrix.c/cpp/pas) 1.1  题目描述 从前有一个的小矩阵,矩阵的每个元素是一个字母(区分大小写),突然有一天它发生了变异,覆盖了整个二维空间,即不停自我复制产生相同 ...

  9. NOI 2015 滞后赛解题报告

    报同步赛的时候出了些意外.于是仅仅能做一做"滞后赛"了2333 DAY1 T1离线+离散化搞,对于相等的部分直接并查集,不等部分查看是否在同一并查集中就可以,code: #incl ...

随机推荐

  1. 剖析epool

    [01]什么是epool: 当互联网的用户越来越多的时候,人们发现传统的网络io模型,扛不住用户的高并发请求的时候.各个操作系统给出了自己对应的答案, 而linux给出的答案是epool.epool是 ...

  2. 【转载】Unity3D研究院之IOS触摸屏手势控制镜头旋转与缩放

    前几篇文章介绍了很多Unity3D引擎自身的一些问题, 今天我们在回到IOS设备上讨论一些触摸屏幕手势,本章的目标是通过触摸iPhone屏幕手势 实现模型左右的旋转,与模型的缩放. 大家想一想模型的旋 ...

  3. JSP/Servlet Web 学习笔记 DayThree —— 实现一个登陆小界面

    项目说明 利用JSP.HTML.JS实现了一个简易的登陆系统.根据前两天的所学,实现了如下功能: a)用户名.密码验证(不基于数据库,只做一个简单的表单数据获取并验证) b)页面访问次数统计 c)验证 ...

  4. 【DNS】- 域名解析中A记录、CNAME、MX记录、NS记录的区别和联系

    1. A记录 又称IP指向,用户可以在此设置子域名并指向到自己的目标主机地址上,从而实现通过域名找到服务器.说明:·指向的目标主机地址类型只能使用IP地址: 附加说明: 1) 泛域名解析即将该域名所有 ...

  5. 一步步制作RPM包

    一步步制作RPM包 来源 http://blog.51cto.com/laoguang/1103628 一.RPM制作步骤 我们在企业中有的软件基本都是编译的,我们每次安装都得编译,那怎么办呢?那就根 ...

  6. 【BestCoder 1st Anniversary】

    AB题都是签到题.... C 题意: 有一串数列,An=3*n*(n-1)+1 然后要从A数列中选取尽量少个数(可重复),使得Sum(An)=m 题解: 贪心地想,能拿大就拿大很明显就是错的...[哪 ...

  7. 《R语言实战》读书笔记--学习张丹日志

    从张丹的日志(http://blog.fens.me/rhadoop-r-basic/)中第九条对象看到R对象的几个总结: 1.内在属性 mode length 所有对象都有的属性 2.外部属性 at ...

  8. 用基于类的通用视图处理表单(Class-based generic views)

    处理表单通常包含3步: 初始化GET(空白的后者预填充的表单) POST非法数据(通常重新显示带有错误信息的表单) POST合法数据(提交数据并重定向) 为了将你从这些烦人的重复步骤中解救出来,Dja ...

  9. html状态码

    100——客户必须继续发出请求101——客户要求服务器根据请求转换HTTP协议版本 200——交易成功201——提示知道新文件的URL202——接受和处理.但处理未完成203——返回信息不确定或不完整 ...

  10. Linux机器-网卡磁盘监控

    1)实时监控网卡流量的通用脚本: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ...