zoukankan      html  css  js  c++  java
  • POJ2185 Milking Grid [KMP应用]

      一道KMP的好题,可惜数据实在是太弱了。

      给出R*C的字符矩阵,问至少多大面积的小矩阵可以覆盖掉整个大矩阵。很容易想到的解法就是求出循环节然后求最大公倍数,但是这样就忽视了可以不用正好覆盖这个条件,比如aaabaa可以拆成aaab/aa,aaaba/a,aaabaa,而不一定非要拆成4的倍数。正确的做法是求出每一列可能拆分的长度,然后取所有列都可以分的长度中最小的。比如

      abcdeaa
      aaabaaa

      第一个串可以分的长度有5,7,第二个串可以分的长度有4,5,6,7,所以取5作为公共长度。至于怎么求一个字符串所有可以拆分的情况,用KMP处理一遍就可以了,然后从最后一列开始,取i=next[i]直到i=-1,这中间的i-next[i]值都是可取长度,比如aabaabaa,它的next数组是01012345,从最后一列开始,next[8]=5,有8-5=3可取,next[5]=2,有8-2=6可取,next[2]=1,有8-1=7可取,next[1]=0,有8-0=8可取,最终可取的数有3,6,7,8四个数。至于为什么这样做是可行的,想想next数组的性质就知道了,next[i]表示以i结尾的串的前缀和后缀的匹配程度。

      算出宽度后只要将每行的前width个字符作为一个整体,然后KMP求出最小循环节作为height,求出乘积即可。

    #include <stdio.h>
    #include <string.h>
    int r,c;
    char mz[10005][80];
    int ctot[80],next[10005];
    void kmp_next(char *s){
        memset(next,0,5*c);
        next[1]=0,next[0]=-1;
        for(int i=2,j=0;i<=c;i++){
            while(j>0&&s[j+1]!=s[i])j=next[j];
            if(s[j+1]==s[i])j++;
            next[i]=j;
        }
        for(int i=next[c];i!=-1;i=next[i]){
            ctot[c-i]++;
        }
    }
    int kmp_col(){
        memset(next,0,sizeof next);
        next[1]=0;
        for(int i=2,j=0;i<=r;i++){
            while(j>0&&strcmp(mz[j+1]+1,mz[i]+1))j=next[j];
            if(strcmp(mz[j+1]+1,mz[i]+1)==0)j++;
            next[i]=j;
        }
        return r-next[r];
    }
    int solve(){
        memset(ctot,0,sizeof ctot);
        for(int i=1;i<=r;i++){
            kmp_next(mz[i]);
        }
        int width=0;
        for(int i=1;i<=c;i++){
            if(ctot[i]==r){
                width=i;
                break;
            }
        }
        for(int i=1;i<=r;i++){
            mz[i][width+1]='\0';
        }
        return width*kmp_col();
    }
    int main(){
        while(scanf("%d%d",&r,&c)!=EOF){
            for(int i=1;i<=r;i++){
                scanf("%s",mz[i]+1);
            }
            int x=solve();
            printf("%d\n",x);
        }
        return 0;
    }

       

  • 相关阅读:
    [.NET控件]Telerik RadControls for ASP.NET AJAX 2008 Q1 net 2.0 Web.UI
    Cookie对象实战
    怎么样修改地址栏前面的图标
    进程管理工具可以下载使用
    怎样才能实现表格背景图片拉伸
    TabControl控件的最佳实践,可以把一个窗体和用户控件添加进来
    flex+eclipse
    为gridview“删除”列添加确认对话框的方法
    触发器deleted 表和 inserted 表详解!!!
    ExtJs的使用
  • 原文地址:https://www.cnblogs.com/swm8023/p/2620853.html
Copyright © 2011-2022 走看看