POJ 2185 Milking Grid next数组

本文介绍了一种寻找二维矩阵中最小子矩阵的方法,该子矩阵通过重复可覆盖整个矩阵。通过将每行视为一个字符,利用一维问题解决思路,实现了高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时空隧道


题意:
给出一个n行m列的矩阵,要求求出最小子矩阵使得子矩阵重复所得的矩阵可以覆盖当前矩阵…


分析:
最小的子矩阵一定是前缀…
如果这个问题是一维的怎么办…求出nxt数组,ans=m-nxt[m]…
那么现在变为二维了…我们看m只有75,但是n有10000,这显然是让我们把行看成一个字符,O(n)的求出列的一维ans,所以我们暴力求出min(len[i])(1<=i<=n)最小的所有行都满足的重复子串长度…然后求转化为一维的了…


代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
const int maxn=10000+5,maxm=75+5;
int n,m,nxt[maxn],ans,cnt[maxm];
char mp[maxn][maxm];
inline bool check(int x,int y,int lenth){
    for(int i=1;i<=lenth;i++)
        if(mp[x][i]!=mp[y][i])
            return false;
    return true;
}
inline void getnext(int lenth){
    int k;
    nxt[0]=nxt[1]=0;
    for(int i=1;i<n;i++){
        k=nxt[i];
        while(k&&!check(k+1,i+1,lenth))
            k=nxt[k];
        if(check(k+1,i+1,lenth))
            nxt[i+1]=k+1;
        else
            nxt[i+1]=0;
    }
}
inline bool check2(int id,int lenth){
    for(int i=1,j=1;j<=m;i++,j++){
        if(i==lenth+1)
            i=1;
        if(mp[id][i]!=mp[id][j])
            return false;
    }
    return true;
}
signed main(void){
    scanf("%d%d",&n,&m);ans=n*m;
    for(int i=1;i<=n;i++)
        scanf("%s",mp[i]+1);
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(check2(i,j))
                cnt[j]++;
    int x;
    for(x=1;x<m;x++)
        if(cnt[x]==n)
            break;
    getnext(x);
    cout<<(n-nxt[n])*x<<endl;
    return 0;
}

by >_< NeighThorn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值