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 ;

你可能感兴趣的:(poj)