NC16638 carper kmp+滑动窗口 求二维矩阵的最小循环,并且令该循环区间的最大值最小
作者:互联网
链接:https://ac.nowcoder.com/acm/problem/16638
来源:牛客网
题目描述
White Cloud has a rectangle carpet of n∗mn*mn∗m. Grid(i,j)Grid (i,j)Grid(i,j) has a color colorA[i][j]colorA[i][j]colorA[i][j] and a cost costA[i][j]costA[i][j]costA[i][j].White Rabbit will choose a subrectangle BBB of p∗qp*qp∗q from AAA and the color of each grid is colorB[0...p−1][0...q−1]colorB[0...p-1][0...q-1]colorB[0...p−1][0...q−1], the cost of BBB is the (maximum number in the corresponding subrectangle of costA∗(p+1)∗(q+1)costA*(p+1)*(q+1)costA∗(p+1)∗(q+1)).
Then colorBcolorBcolorB is continuously translated and copied in an infinite times, that is, expand colorBcolorBcolorB into an infinite new matrix, colorCcolorCcolorC, which satisfies colorC[i][j]=colorB[imodp][jmodq]colorC[i][j]=colorB[i mod p][j mod q]colorC[i][j]=colorB[imodp][jmodq].
White Rabbit must ensure that colorAcolorAcolorA is a subrectangle of colorCcolorCcolorC.
You need to find the minimum cost way.
输入描述:
The first line of input contains two integers n,m(0<n∗m≤1000000)n,m(0<n*m \leq 1000000)n,m(0<n∗m≤1000000)
For the next line of nnn lines, each line contains mmm lowercase English characters, denoting colorAcolorAcolorA.
For the next line of nnn lines, each line contains mmm integers in range [0,1000000000], denoting costAcostAcostA.
输出描述:
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 copies
colorC=
cacacacaca ...
cacacacaca ...
cacacacaca ...
cacacacaca ...
cacacacaca ...
.........
colorA is a subrectangle of colorC
the cost is max(3,1)*(1+1)*(2+1).
分析:
求二维矩阵的最小循环,并且令该循环区间的最大值最小
kmp + 滑动窗口
#include<bits/stdc++.h> using namespace std; const int N = 1e6+10; struct KMP { int nxt[N],len;//表示和 i 位置相等的真前缀和真后缀的长度 char t[N]; void clear() { len = nxt[0] = nxt[1] = 0; } /* 1-bas */ /* 注意在ss结尾添加‘\0’ */ void init(char* ss) { len = strlen(ss+1); memcpy(t,ss,(len+2)*sizeof(char)); for(int i = 2;i<=len;i++) { nxt[i] = nxt[i-1]; while(nxt[i] && ss[i] != ss[nxt[i] + 1]) nxt[i] = nxt[nxt[i]]; nxt[i] += (ss[i] == ss[nxt[i]+1]); } } /* 求所有在ss串中的start_pos. 如果first_only设置为true,则只返回第一个位置*/ vector<int> match(char *ss,bool first_only = false) { int len_s = strlen(ss+1); vector<int> start_pos(0); for(int i = 1,j = 1;i<=len_s;++i) { while(j!=1 && ss[i] != t[j]) j = nxt[j-1] + 1; if(ss[j] == t[j]) j ++ ; if(j == len + 1) { start_pos.push_back(i - len + 1); if(first_only) return start_pos; j = nxt[len] + 1; } } return start_pos; } void debug() { for(int i = 0;i<=len;i++) { printf("[debug] nxt[%d]=%d\n",i,nxt[i]); } } /* 循环周期 形如 acaca 中 ac 是一个合法周期 */ vector<int> periodic() { vector<int> ret; int now = len; while(now) { now = nxt[now]; ret.push_back(len - now); } return ret; } /* 循环节 形如 acac 中ac、acac是循环节,aca不是*/ vector<int> periodic_loop() { vector<int> ret; for(int x:periodic()) { if(len % x == 0) ret.push_back(x); } return ret; } int min_periodic_loop() { return periodic_loop()[0]; } }kmper; vector<string> s; vector<vector<int>> a,maxVal; int cnt1[N],cnt2[N],n,m; char S[N]; pair<int,int> pq[N];int l,r; int main() { cin>>n>>m; s.resize(n+1); maxVal.resize(n+1); for(int i = 1;i<= n;i ++ ) { cin>>s[i]; } a.resize(n+1); for(int i = 1;i<= n;i++ ) { a[i].resize(m+1); maxVal[i].resize(m+1); for(int j = 1;j<= m;j++) { cin>>a[i][j]; } } int p,q;kmper.clear(); for(int i = 1;i<=n;i++) { for(int j = 1;j<=m;j++) { S[j] = s[i][j-1]; } S[m+1] = '\0'; kmper.init(S); for(int x:kmper.periodic()) { cnt1[x] ++ ; } } for (int j=1;j<=m;j++){ for (int i=1;i<=n;i++){ S[i] = s[i][j-1]; } S[n+1]='\0'; kmper.init(S); for (int x:kmper.periodic()){ cnt2[x]++; } } for (int i=N;i>=1;i--){ if (cnt1[i]==n){ q = i; } if (cnt2[i]==m){ p=i; } } for (int i=1;i<=n;i++){ l = 0,r=0; for (int j=1;j<=m;j++){ while (r>l&&pq[l].second<=j-q)l++; while (r>l&&pq[r-1].first<=a[i][j])r--; pq[r++] = {a[i][j],j}; if (j>=q){ maxVal[i][j-q+1] = pq[l].first; } } } int ans = 0x3f3f3f3f; for (int j=1;j<=m-q+1;j++){ l=r=0; for (int i=1;i<=n;i++){ while (r>l&&pq[l].second<=i-p)l++; while (r>l&&pq[r-1].first<=maxVal[i][j])r--; pq[r++] = {maxVal[i][j],i}; if (i>=p){ ans = min(ans,pq[l].first); } } } cout<<1LL*(p+1)*(q+1)*ans<<endl; return 0; }
标签:vector,...,pq,int,令该,最小,len,循环,colorB 来源: https://www.cnblogs.com/er007/p/16685291.html