算法竞赛进阶指南---0x18(KMP)Milking Grid

题面

在这里插入图片描述

题解

  1. 对于求一个最小覆盖矩阵,我们可以横纵分开来求,先看横向,对于每行,我们直接暴力枚举循环节长度,判断每一行是否符合,最后得到一个横向的最小循环节长度(width)
  1. 对于纵向,我们就可以将每一行看作是一个字母,然后进行纵向的KMP,求出ne数组,那么n-ne[n] 就是最小循环节长度(heigth)
  1. 解释1:为什么求出最小的横向循环节就能得到最后最小的面积,而不是让width 大点,heigth小点,因为如果让width大点,那么只会在求纵向KMP的时候,不同的字符串更多,所求的ne数组的值变小,heigth变大
  1. 解释2:能否在求横向循环节的时候,求出每一行的最小循环节然后再取最小公倍数,当然不能,因为对于abcabcabc 这样的字符串循环节可以是3(abc),6(abcabc),9 没错是3的倍数,但是对于aaabaa ,循环节可以是4(aaab),5(aaaba),这样就不具有倍数关系,所以不能求最小公倍数,当然更不能取每行的一个最大数,只能是从1到m枚举循环节的长度,看每行是否满足
  1. 题中给定m<=75,n<10000 ,那么对于 O(n2 *m) 我们是可以接受的

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 10010, M = 80;

int n, m;
char str[N][M];
int ne[N];
bool st[M];

int main() {
    
    

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    memset(st, true, sizeof st);

    cin >> n >> m;

    //横向暴力枚举
    for (int i = 1; i <= n; i++) {
    
    
        cin >> str[i];
        for (int j = 1; j <= m; j++) {
    
    
            if (st[j]) {
    
    
                for (int k = j; k < m; k += j) {
    
    
                    for (int u = 0; u < m && u + k < m; u++) {
    
    
                        if (str[i][u] != str[i][u + k]) {
    
    
                            st[j] = false;
                            break;
                        }
                    }
                    if (!st[j]) break;
                }
            }
        }
    }

    int width;
    for (int i = 1; i <= m; i++) {
    
    
        if (st[i]) {
    
    
            width = i;
            break;
        }
    }

    //将每行的循环节转化为字符串
    for (int i = 1; i <= n; i++) str[i][width] = '\0';

    //纵向KMP(将每行看成一个字母)
    for (int i = 2, j = 0; i <= n; i++) {
    
    
        while (j && strcmp(str[i], str[j + 1])) j = ne[j];
        if (!strcmp(str[i], str[j + 1])) j++;
        ne[i] = j;
    }

    int heigth = n - ne[n];

    cout << heigth * width << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/114107904