ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NC16638 carper kmp+滑动窗口 求二维矩阵的最小循环,并且令该循环区间的最大值最小

2022-09-12 01:30:22  阅读:204  来源: 互联网

标签:vector ... pq int 令该 最小 len 循环 colorB


 链接: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有