难啊,多校当时根本不会做

题目描述

White Cloud has a rectangle carpet of n*m. Grid (i,j) has a color colorA[i][j] and a cost costA[i][j].
White Rabbit will choose a subrectangle B of p*q from A and the color of each grid is colorB[0...p-1][0...q-1], the cost of B is the (maximum number in the corresponding subrectangle of costA*(p+1)*(q+1).
Then colorB is continuously translated and copied in an infinite times, that is, expand colorB into an infinite new matrix, colorC, which satisfies colorC[i][j]=colorB[i mod p][j mod q].
White Rabbit must ensure that colorA is a subrectangle of colorC.
You need to find the minimum cost way.

输入描述:

The first line of input contains two integers n,m(0<n*m <= 1000000)
For the next line of n lines, each line contains m lowercase English characters, denoting colorA.
For the next line of n lines, each line contains m integers in range [0,1000000000], denoting costA.

输出描述:

Print the minimum cost.

示例1

输入

2 5
acaca
acaca
3 9 2 8 7
4 5 7 3 1

输出

18

说明

choose subrectangle colorA[1...1][3...4]=ca, After copying unlimited copiescolorC=cacacacaca ...cacacacaca ...cacacacaca ...cacacacaca ...cacacacaca ............colorA is a subrectangle of colorCthe cost is max(3,1)*(1+1)*(2+1).

题目大意:有一个n*m的矩阵A,每个位置有一个字符和一个权值,现在要找一个子矩阵,使得这个子矩阵是A的一个 循环节,并最小化子矩阵的权值最大值。

做法
首先要找到矩阵的一个最小的循环节,假设是p和q,那么最优解就一定是选一个p*q的子矩形。
如何求最小的循环节?行和列可以独立考虑。 求列的循环节时,我们可以对每一行做一次kmp,找到这些行的最大公共循环节。 求行的循环节时,我们可以对每一列做一次kmp,找到这些列的最大公共循环节。
接下来问题就变成了,求所有大小为p*q的子矩形的最大值的最小值。可以采用单调队列,求出 所有p*q的子矩形的最大值,然后找一个最小的即可。

标程:(肯定不是我写的哈哈)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<assert.h>
using namespace std;
int gi() {int w;char c;while (((c=getchar())<'0'||'9'<c)&&c!='-');w=c-'0';while ('0'<=(c=getchar())&&c<='9') w=(w<<3)+(w<<1)+c-'0';return w;
}
const int seed=131;
const int mod=1e9+7;
const int N=1e6+100;
int h[N],L[N],nxt[N];
inline int kmp(int *a,int n) {nxt[0]=0;int i,c,p;for (i=1;i<n&&a[i]==a[i+1];i++);i--;nxt[2]=i;c=2,p=2+nxt[2]-1;if (nxt[2]==n-1) return 1;for (i=3;i<=n;i++) {if (p<i||p-i+1<=nxt[i-c+1]) {nxt[i]=max(p-i+1,0);while (a[nxt[i]+i]==a[nxt[i]+1]) nxt[i]++;if (i+nxt[i]>n) return i-1;c=i,p=i+nxt[i]-1;}else nxt[i]=nxt[i-c+1];}return n;
}
int Val[N],Q[N];
#define val(x,y) Val[((x)-1)*m+(y)]
#define q(x,y) Q[((x)-1)*m+(y)]
int l[N],r[N],n,m;
int qq[N],w[N];
int key[26];
char s[N];
int main() {int i,j,a,b,ll,rr;char c;int ans=2147483647;n=gi(),m=gi();assert(0<n*m&&n*m<=1e6);for (i=0;i<26;i++) key[i]=rand();for (i=1;i<=n;i++) {scanf("%s",s+1);assert(strlen(s+1)==m);for (j=1;j<=m;j++) {c=s[j];assert('a'<=c&&c<='z');h[i]=(1LL*h[i]*seed+key[c-'a'])%mod;L[j]=(1LL*L[j]*seed+key[c-'a'])%mod;}}a=kmp(h,n);b=kmp(L,m);for (i=1;i<=n;i++) for (j=1;j<=m;j++) val(i,j)=gi(),assert(0<=val(i,j)&&val(i,j)<=1e9);for (i=1;i<=n;i++) l[i]=1,r[i]=0;for (j=1;j<b;j++)for (i=1;i<=n;i++) {while (l[i]<=r[i]&&val(i,j)>=val(i,q(i,r[i]))) r[i]--;q(i,++r[i])=j;}for (j=b;j<=m;j++) {ll=1,rr=0;for (i=1;i<a;i++) {if (l[i]<=r[i]&&q(i,l[i])<=j-b) l[i]++;while (l[i]<=r[i]&&val(i,j)>=val(i,q(i,r[i]))) r[i]--;q(i,++r[i])=j;while (ll<=rr&&val(i,q(i,l[i]))>=qq[rr]) rr--;qq[++rr]=val(i,q(i,l[i])),w[rr]=i;}for (i=a;i<=n;i++) {if (l[i]<=r[i]&&q(i,l[i])<=j-b) l[i]++;while (l[i]<=r[i]&&val(i,j)>=val(i,q(i,r[i]))) r[i]--;q(i,++r[i])=j;if (ll<=rr&&w[ll]<=i-a) ll++;while (ll<=rr&&val(i,q(i,l[i]))>=qq[rr]) rr--;qq[++rr]=val(i,q(i,l[i])),w[rr]=i;ans=min(ans,qq[ll]);}}cout<<1LL*(a+1)*(b+1)*ans<<endl;return 0;
}

多校一道KMP+DP的题相关推荐

  1. 算法 --- 记一道面试dp算法题

    题目: 给定一个数组(长度大于1),如下 let a = [1,4,3,4,5] // 长度不确定,数值为整数 要求写一个函数,返回该数组中,除本身数字之外其他元素的成积.即返回如下: // 过程[4 ...

  2. 【每日DP】day2、P1879 [USACO06NOV]Corn Fields G玉米地(状压DP模板题)难度⭐⭐⭐★

    昨天的每日DP我还在写01背包,今天就到状压DP了,真刺激. P1879 [USACO06NOV]Corn Fields G 题目链接 输入 2 3 1 1 1 0 1 0 输出 9 一道简单的状压D ...

  3. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  4. ACW各种dp模板题 day29

    背包的就不贴上来了 感觉没啥好说的 AcWing 898. 数字三角形 线性dp 第一题 应该都是一眼秒吧 感觉自己第一遍学的时候是真的菜 呃呃 我们注意边界情况就可以了 状态转移没啥好说的 下一道 ...

  5. 洛谷P3146 区间dp做题笔记

    不是题解,不是题解,不是题解,纯属个人笔记,不知所言. 传送门:P3146 问:什么时候才能写的一手漂亮的dp? 答:夜深人静之时,魂归故里之日. 此题是一道基础的区间dp的题,看完题解犹豫片刻,之后 ...

  6. dp百题大过关(第一场)

    好吧,这名字真是让我想起了某段被某教科书支配的历史.....各种DP题层出不穷,不过终于做完了orz 虽然各种手糊加乱搞,但还是要总结一下. T1 Monkey Banana Problem    这 ...

  7. HDU 2196 Computer 树形DP经典题

    链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问 ...

  8. HDU - 4552 怪盗基德的挑战书(后缀数组+RMQ/KMP+dp)

    题目链接:点击查看 题目大意:给出一个字符串,统计每个前缀在字符串中出现的次数之和 题目分析:可以直接先用后缀数组跑出来height,再用RMQ跑出来任意两个后缀的height,我们可以将题意转换为求 ...

  9. POJ 1155 TELE 背包型树形DP 经典题

    由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送 ...

最新文章

  1. 高并发下如何保证接口的幂等性?
  2. 记一次有惊无险的 JVM 优化经历!
  3. hibernate.hbm2ddl.auto配置详解
  4. CEO 赠书 |《跨越鸿沟》如何将梦想变为现实?
  5. 黑客帝国 数字雨 屏幕保护程序 linux ubuntu
  6. UTD2202C示波器如何显示峰峰值
  7. 在自己本地原有的镜像基础上用dockerfile加一下库进去
  8. ARM ADS中的AXD 调试经验集锦
  9. windows10 安装 choco
  10. java8中的Stream流式操作总结,List转Map或List转LinkedHashMap使用Collectors.groupingBy用法
  11. WKWebView预初始化
  12. 运算器和控制器的组成部件及功能
  13. TPM分析笔记(九)TPM资源实体-句柄
  14. Writing an LLVM Pass
  15. 在使用DTX-1800测试网线(特别是短跳线),回波损耗为负值,为什么结果是PASS?
  16. Mac AndroidStudio .9图片制作
  17. ubuntu赋予当前用户root权限
  18. 人关节软骨细胞的体外培养
  19. seaborn使用boxplot函数进行箱图可视化(使用色彩调色板自定义设置箱图的颜色、sns.set_palette全局设置palette参数、自定义全局调色板色彩)
  20. presto sql语法总结

热门文章

  1. python开发视频播放器_Python应用03 使用PyQT制作视频播放器实例
  2. python代做在哪找靠谱_比较靠谱的资产评估师考试去哪找
  3. 在UE中自由绘制基本图元的几种方法
  4. 为Ubuntu安装build-essential软件包
  5. Linux 定时器设置
  6. java float什么类型数据类型_Java中的Float和double数据类型
  7. 【转】Dynamics CRM 365零基础入门学习(七)Dynamics 365 DataMigrationUtility tool使用
  8. 32命令模式(Command Pattern)
  9. 华为鸿蒙与佳华,华为鸿蒙系统发布,带来三大好消息
  10. python断点调试_「Python调试器」,快速定位各种疑难杂症!!!