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 ;

原文地址:https://www.cnblogs.com/xiaolongchase/p/2339191.html