zoukankan      html  css  js  c++  java
  • poj2185(kmp算法next数组求最小循环节,思维)

    题目链接:https://vjudge.net/problem/POJ-2185

    题意:给定由大写字母组成的r×c矩阵,求最小子矩阵使得该子矩阵能组成这个大矩阵,但并不要求小矩阵刚好组成大矩阵,即边界部分可以空缺(见样例)。

    思路:
      把每一行视作一个字符,然后对r行求next数组,那么r-nex[r]即为以行为单元的最小循环节大小ans1。

      把每一列视作一个字符,然后对c列求next数组,那么c-nex[c]即为以列为单元的最小循环节大小ans2。

      最终答案即ans1*ans2。(子矩阵的面积)

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxr=10005;
    const int maxc=80;
    char s[maxr][maxc];
    int ans1,ans2,r,c,nex1[maxr],nex2[maxc];
    
    bool check1(int i,int j){
        for(int k=0;k<c;++k)
            if(s[i][k]!=s[j][k])
                return false;
        return true;
    }
    
    bool check2(int i,int j){
        for(int k=0;k<r;++k)
            if(s[k][i]!=s[k][j])
                return false;
        return true;
    }
    
    void get_next1(){
        int j;
        j=nex1[0]=-1;
        for(int i=1;i<r;++i){
            while(j>-1&&!check1(i,j+1)) j=nex1[j];
            if(check1(i,j+1)) ++j;
            nex1[i]=j;
        }
    }
    
    void get_next2(){
        int j;
        j=nex2[0]=-1;
        for(int i=1;i<c;++i){
            while(j>-1&&!check2(i,j+1)) j=nex2[j];
            if(check2(i,j+1)) ++j;
            nex2[i]=j;
        }
    }
    
    int main(){
        scanf("%d%d",&r,&c);
        for(int i=0;i<r;++i)
            scanf("%s",s[i]);
        get_next1();
        get_next2();
        ans1=r-(nex1[r-1]+1);
        ans2=c-(nex2[c-1]+1);
        printf("%d
    ",ans1*ans2);
        return 0;
    }
  • 相关阅读:
    第一次博客作业
    面向对象及软件工程-团队作业4
    面向对象及软件工程-团队作业3
    面向对象及软件工程-团队作业2
    面向对象及软件工程-个人作业2(59)
    面向对象及软件工程-团队作业1
    面向对象及软件工程-个人作业1
    数据结构:第八章学习小结
    数据结构:第七章学习小结
    数据结构:第六章学习小结
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11797721.html
Copyright © 2011-2022 走看看