• poj2185(kmp)


    题目链接: http://poj.org/problem?id=2185

    题意: 给出一个矩形字符块, 求能组成该矩形块的最小子矩形块.

    思路: 将每行字符串当作一个字符,那么原矩形字符块就成了一列字符,其最小循环节即为所求矩形块的宽;

    将每列字符串当作一个字符,那么原矩形字符块就成了一行字符,其最小循环节即为所求矩形的长.

    代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 using namespace std;
     4 
     5 const int MAXN = 1e5 + 10;
     6 int nxt1[MAXN], nxt2[80];
     7 char str[MAXN][80];
     8 int n, m;
     9 
    10 bool equal1(int x, int y){//判断两行字符串是否相等
    11     for(int i = 0; i < m; i++){
    12         if(str[x][i] != str[y][i]) return false;
    13     }
    14     return true;
    15 }
    16 
    17 bool equal2(int x, int y){//判断两列字符串是否相等
    18     for(int i = 0; i < n; i++){
    19         if(str[i][x] != str[i][y]) return false;
    20     }
    21     return true;
    22 }
    23 
    24 void get_nxt1(void){ //将每行字符串当作一个字符,求矩形字符块变成字符串后的nxt数组
    25     int i = 0, j = -1;
    26     nxt1[0] = -1;
    27     while(i < n){
    28         if(j == -1 || equal1(i, j)) nxt1[++i] = ++j;
    29         else j = nxt1[j];
    30     }
    31 }
    32 
    33 void get_nxt2(void){ //将每列字符串当作一个字符,求矩形字符块变成字符串后的nxt数组
    34     int i = 0, j = -1;
    35     nxt2[0] = -1;
    36     while(i < m){
    37         if(j == -1 || equal2(i, j)) nxt2[++i] = ++j;
    38         else j = nxt2[j];
    39     }
    40 }
    41 
    42 int main(void){
    43     scanf("%d%d", &n, &m);
    44     for(int i = 0; i < n; i++){
    45         scanf("%s", str[i]);
    46     }
    47     get_nxt1();
    48     get_nxt2();
    49     int cnt1 = n - nxt1[n];
    50     int cnt2 = m - nxt2[m];
    51     printf("%d
    ", cnt1 * cnt2);
    52     return 0;
    53 }
    View Code
  • 相关阅读:
    容斥原理
    m元集A到n元集B的满射的个数
    二项式反演公式
    多项式定理
    组合数的基本性质
    Luogu P2408 不同子串个数
    Luogu P5410【模板】扩展 KMP
    Luogu P2336 [SCOI2012]喵星球上的点名
    Luogu P2852 [USACO06DEC]牛奶模式Milk Patterns
    Luogu P4248 [AHOI2013]差异
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7351642.html
Copyright © 2020-2023  润新知