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

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

题目描述

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

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

已经被它占领了,但你只被告知了大小为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. Java基础-8构造方法

    一).构造方法: 在之前我们提到对象的概念以及对象的实例化等,在这里简单回顾下: Man man = new Man(); 语句创建一个对象,new可以理解成创建一个对象的关键字,通过new关键字为对 ...

  2. PAT——甲级1009:Product of Polynomials;乙级1041:考试座位号;乙级1004:成绩排名

    题目 1009 Product of Polynomials (25 point(s)) This time, you are supposed to find A×B where A and B a ...

  3. PHP连接mysql数据库进行增删改查--修稿数据

    <?php $id = $_GET['id']; $db = new Mysqli("localhost","root","root" ...

  4. 冒泡排序js

    //    冒泡排序     var a = [1,3,2,4,5,3,2,1,4,6,7,7,6,6];     var b =[];     for(var i=0;i<a.length;i ...

  5. 实用JS系列——面向对象中的类和继承

    背景: 在最开始学习JavaScript时,我们就知道,它是一种脚本语言,也有面向对象机制.但它的面向对象继承机制是基于原型的,即Prototype.今天,我们就来找一下JS中OO的影子. 创建类 1 ...

  6. POJ 2115 C-Looooops | exgcd

    题目 给出一个循环for(int i=A;i!=B;i+=C) 在mod (1<<k) 下是否可以退出循环 是,输出时间,否输出FORVEER 题解: 题意可以变换成 A+Cx=B (mo ...

  7. transform perspective的层级问题

    如上图,在积分的数字元素上,使用了transform perspective,其层级就穿透了上面的遮罩层,关键代码如下: .mask { position: fixed; z-index:; } .f ...

  8. 【CF Round 439 B. The Eternal Immortality】

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...

  9. JavaScript的团队编程规范

    本规范是针对javascript函数式编程风格与公司严重依赖于jQuery进行编码的现实制定出来. 禁止使用eval,with与caller(ecma262 v5 的use strict要求).eva ...

  10. POJ2187 旋转卡壳 求最长直径

    给定平面上的一些散点集,求最远两点距离的平方值. 题解: 旋转卡壳求出凸包,然后根据单调性,求出最远两点的最大距离 #pragma GCC optimize(2) #pragma G++ optimi ...