• poj(2185) Milking Grid (很好的kmp题目)


    http://poj.org/problem?id=2185

    题意:给你一个字符矩阵,求出它的最小覆盖子矩阵,即使得这个子矩阵的无限复制扩张之后的矩阵,能包含原来的矩阵。 即二维的最小覆盖子串。

    思路:KMP很好的一道题。首先易证:最小覆盖子矩阵一定靠左上角。那么,我们考虑求出每一行的最小重复串长度,所有行的最小重复串的长度的lcm就是最小重复子矩阵的宽。然后我们对列也做相同的操作。于是我们就可以求得最小重复子矩阵的大小了。(这里要注意一点:当所得的宽大于原来的宽时,就让等于原来的宽,长也如此)。算法实现:算法的核心在于高效的求出每一行和每一列的最小重复串,这个可以最原串做一次KMP中的get_next()。

    如果对于最小区间覆盖不了解的话,请移步:http://blog.csdn.net/fjsd155/article/details/6866991

    (注:以上部分为转载)

     

    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include <string.h>
    #include <algorithm>
    #include <stdlib.h>
    #include <math.h>
    #include <vector>
    #include <map>
    using namespace std;
    const int maxn = 10001;
    char grid[maxn][76];
    int next[maxn];
    int r,c;
    int res1,res2;
    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;
    }
    void getnext_r(int x){
        int i = 0,j = -1;
        next[0] = -1;
        while(i < c){
            if(j == -1 || grid[x][i] == grid[x][j])
                next[++i] = ++j;
            else
                j = next[j];
        }
        res1 = lcm(res1,c - next[c]);
    }
    void getnext_c(int x){
        int i = 0,j = -1;
        next[0] = -1;
        while(i < r){
            if(j == -1 || grid[i][x] == grid[j][x])
                next[++i] = ++j;
            else
                j = next[j];
        }
        res2 = lcm(res2,r - next[r]);
    }
    int main(){
        while(~scanf("%d%d",&r,&c)){
            for(int i = 0;i < r;i++)
                scanf("%s",grid[i]);
            res1 = 1;
            for(int i = 0;i < r;i++){
                getnext_r(i);
                if(res1>=c){
                    res1 = c;
                    break;
                }
            }
            res2 = 1;
            for(int i = 0;i < c;i++){
                getnext_c(i);
                if(res2>=r){
                    res2 = r;
                    break;
                }
            }
            printf("%d\n",res1*res2);
        }
        return 0;
    }

     

     

  • 相关阅读:
    数据移除的循环
    C#窗体多语言切换(简繁)
    C# 文字转换最简单的方法
    使用CodeDOM动态编译一个字符串表达式
    C#设置WebBrowser默认浏览器
    Image和字节数组互转
    苹果手机的SB系列(8)为什么没有短信全部删除?
    循环删除外键约束
    腾讯云COS自定义域名,支持https,CDN,私有访问
    腾讯云COS请求签名C#版
  • 原文地址:https://www.cnblogs.com/Roly/p/3053240.html
Copyright © 2020-2023  润新知