zoukankan      html  css  js  c++  java
  • poj 3080 Blue Jeans (KMP)

    给定n个字符串,求最长公共子串。

    利用KMP是对子串从1..j匹配母串,枚举第一个母串的所有后缀子串,在KMP匹配过程中得到j的最大值(这里不能完全匹配后再得最大值,为了确保取到所有子串),对n-1个母串匹配完成后,j最大值的最小值便为公共子串。若有多个这样的子串,字典顺序小者为result。

    这里用到了string的两个函数,strcpy(substr, str)和strncpy(substr, str, n)。前者是复制到空字符停止复制,后者则是先找到n个字符再开始复制。使用后者后,要对复制所得字符串封存,substr[n] = '\0',因为这里不知道,WA了好多次...而且好像strcpy(substr, str+i)可行,但strcpy(substr+j, str+i)不可行,让我不得不改了下get_next()和kmp()中的模板部分。

    补充:刚刚做完3450那题,基本和这题一样,但是让我发现了一个对此题没有影响的BUG。若没有result.len>=3 这个条件,输入abc  cde是得不到结果c的,原因在于我的KMP结束后返回的max是substr的下标,也就是说max=3则说明取substr[0..3]四个字符,当只有一个字符时max=0,若m初始化为0,则没有字符符合时返回也为0。

    就这点小BUG让我调3450调了3个小时。。共WA14次。。 

    code:

    #include<cstdio>
    #include<cstring>
    char str[10][62] ;
    char substr[62] ;
    char result[62] ;
    char temp[62] ;
    int next[62] ;
    int len, n, max ;
    void get_next(){
        next[0] = -1 ;
        int j = -1 ;
        for(int i=1; i<len; i++){
            while(j>-1&&substr[j+1]!=substr[i])
                j = next[j] ;
            if(substr[j+1]==substr[i])  j ++ ;
            next[i] = j ;
        }
    }
    void kmp(){
        int j, m ;
        get_next() ;
        for(int k=1; k<n; k++){
            j = -1, m = -1 ;//m最好取-1
            for(int i=0; i<60; i++){
                while(j>-1&&substr[j+1]!=str[k][i])
                    j = next[j] ;
                if(substr[j+1]==str[k][i]) j ++ ;
                if(j>m) m = j ; //m取可匹配到的最大值
            }
            if(m<max)   max = m ;//max取可匹配到的最小值,公共子串以最小者为准
        }
    }
    int main(){
        int t, i, ans ;
        scanf("%d", &t) ;
        while(t--){
            scanf("%d", &n) ;
            for(i=0; i<n; i++)
                scanf("%s", str[i]) ;
            ans = 0 ;
            for(i=0; i<58; i++){
                strcpy(substr, str[0]+i) ;//枚举第一个串的所有后缀串
                len = 60 - i ;
                max = 65 ;
                kmp() ;
                if(max>ans){
                    ans = max ;
                    strncpy(result, str[0]+i, ans+1) ;
                    result[ans+1] = '\0' ;
                }else if(max==ans){ //若有相等长度,取字典序小者
                    strncpy(temp, str[0]+i, ans+1) ;
                    temp[ans+1] = '\0' ;
                    if(strcmp(result, temp)>0)
                        strcpy(result, temp) ;
                }
            }
            if(ans>=2)
                printf("%s\n", result) ;
            else
                printf("no significant commonalities\n") ;
        }
        return 0 ;

  • 相关阅读:
    __dopostback的用法
    Asp.net MVC中防止HttpPost重复提交
    分享SQL2005 查询表结构的SQL语句
    SQL Server char nchar varchar nvarchar的区别
    SQL2005中的XXproperty() 函数归纳
    QQ登录端口研究
    关于SQLSERVER的全文目录跟全文索引的区别
    版本管理软件VisualSVN、TortoiseSvn、AnkhSvn 后记
    SCREEN2EXE视频录像软件 提供技术支持的好帮手
    介绍一款替代SSMS的sqlserver管理工具 toad for sqlserver5.7
  • 原文地址:https://www.cnblogs.com/xiaolongchase/p/2339191.html
Copyright © 2011-2022 走看看