poj 2185 Milking Grid

本文介绍了一种寻找字符矩阵中最短循环子串的方法,并通过计算各行列的循环子串长度来确定整个矩阵的最小重复单元,最终求得能够构成原矩阵的最小子矩阵大小。

  给你一个字符矩阵,然后在这个矩阵中找子矩阵,要求这个子矩阵的字符数最少,且能用这个子字符串拼成包含该字符矩阵(或者就是该字符矩阵)的字符矩阵。

开始我理解的时候,觉得可以换这个子矩阵的方向,结果看着别人都是直接用原始方向,不知道是我读题不仔细还是这题的信息有缺省,反正这题如果子字符串能转动,

那么这题肯定很麻烦,但是如果不变方向,直接求每行的循环子串的字符数,然后求lcm所有行的循环子串的字符串。列也按照同样的方法进行处理,然后2个相乘就解决了。这里需要注意一点,如果这个lcm超过了行或者列的总长度,直接取长度就行。


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Maxr = 10010, Maxl = 80;

char str[Maxr][Maxl];
int r, l, next[Maxr], lent;

int get_next_r(int x) {
    int i = 0, j = -1;
    next[0] = j;
    while(i < l) {
        if(j == -1||str[x][j] == str[x][i])
        {
            i++, j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
        return i - next[i];
}

int get_next_c(int x) {
    int i = 0, j = -1;
    next[0] = j;
    while(i < r) {
        if(j == -1||str[j][x] == str[i][x])
        {
            i++, j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
    return i - next[i];
}


int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}

int lcm(int a,int b) {
    return a/gcd(a, b)*b;
}

int main(void)
{
    while(scanf("%d%d",&r,&l)!=EOF) {
        for(int i = 0; i < r; ++i)
        {
            scanf("%s",str[i]);
        }
        int lr = 1, ll = 1;
        for(int i = 0; i < r; ++i) {
            lr = lcm(lr,get_next_r(i));
        }
        if(lr > l)
            lr = l;

        for(int i = 0; i < l; ++i) {
            ll = lcm(ll,get_next_c(i));
        }
        if(ll > r)
            ll = r;
        cout<<ll*lr<<endl;
    }
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值