C數據結構 - KMP算法的實現

jopen 9年前發布 | 1K 次閱讀 C/C++

// KMP字符串模式匹配算法
// 輸入: S是主串,T是模式串,pos是S中的起始位置
// 輸出: 如果匹配成功返回起始位置,否則返回-1
int KMP(PString S, PString T, int pos)
{
    assert(NULL != S);
    assert(NULL != T);
    assert(pos >= 0);
    assert(pos < S->length);

if (S->length < T->length)
    return -1;

printf("主串\t = %s\n", S->str);
printf("模式串\t = %s\n", T->str);

int *next = (int *)malloc(T->length * sizeof(int));
// 得到模式串的next數組
GetNextArray(T, next);

int i, j;
for (i = pos, j = 0; i < S->length && j < T->length; )
{
    // i是主串游標,j是模式串游標
    if (-1 == j ||                // 模式串游標已經回退到第一個位置
        S->str[i] == T->str[j]) // 當前字符匹配成功
    {
        // 滿足以上兩種情況時兩個游標都要向前進一步
        ++i;
        ++j;
    }
    else                        //  匹配不成功,模式串游標回退到當前字符的next值
    {
        j = next[j];
    }
}

free(next);

if (j >= T->length)
{
    // 匹配成功
    return i - T->length;
}
else
{
    // 匹配不成功
    return -1;
}

}

// 得到字符串的next數組 void GetNextArray(PString pstr, int next[]) { assert(NULL != pstr); assert(NULL != next); assert(pstr -> length > 0 );

 //  第一個字符的next值是-1,因為C中的數組是從0開始的
 next[ 0 ]  =   - 1 ;
 for  ( int  i  =   0 , j  =   - 1 ; i  <  pstr -> length  -   1 ; )
 {
     //  i是主串的游標,j是模式串的游標
     //  這里的主串和模式串都是同一個字符串
      if  ( - 1   ==  j  ||                          //  如果模式串游標已經回退到第一個字符
         pstr -> str[i]  ==  pstr -> str[j])     //  如果匹配成功
      {
         //  兩個游標都向前走一步
          ++ i;
         ++ j;
         //  存放當前的next值為此時模式串的游標值
         next[i]  =  j;
    }
     else                                  //  匹配不成功j就回退到上一個next值
      {
        j  =  next[j];
    }
}

}

include < stdio.h >

include < stdlib.h >

include < assert.h >

include < string .h >

define MAX_LEN_OF_STR 30 // 字符串的最大長度

typedef struct String // 這里需要的字符串數組,存放字符串及其長度 { char str[MAX_LEN_OF_STR]; // 字符數組 int length; // 字符串的實際長度 } String, * PString;

// 得到字符串的next數組 void GetNextArray(PString pstr, int next[]) { assert(NULL != pstr); assert(NULL != next); assert(pstr -> length > 0 );

 //  第一個字符的next值是-1,因為C中的數組是從0開始的
 next[ 0 ]  =   - 1 ;
 for  ( int  i  =   0 , j  =   - 1 ; i  <  pstr -> length  -   1 ; )
 {
     //  i是主串的游標,j是模式串的游標
     //  這里的主串和模式串都是同一個字符串
      if  ( - 1   ==  j  ||                          //  如果模式串游標已經回退到第一個字符
         pstr -> str[i]  ==  pstr -> str[j])     //  如果匹配成功
      {
         //  兩個游標都向前走一步
          ++ i;
         ++ j;
         //  存放當前的next值為此時模式串的游標值
         next[i]  =  j;
    }
     else                                  //  匹配不成功j就回退到上一個next值
      {
        j  =  next[j];
    }
}

}

// KMP字符串模式匹配算法 // 輸入: S是主串,T是模式串,pos是S中的起始位置 // 輸出: 如果匹配成功返回起始位置,否則返回-1 int KMP(PString S, PString T, int pos) { assert(NULL != S); assert(NULL != T); assert(pos >= 0 ); assert(pos < S -> length);

 if  (S -> length  <  T -> length)
     return   - 1 ;

printf( " 主串\t = %s\n " , S -> str);
printf( " 模式串\t = %s\n " , T -> str);

 int   * next  =  ( int   * )malloc(T -> length  *   sizeof ( int ));
 //  得到模式串的next數組
 GetNextArray(T, next);

 int  i, j;
 for  (i  =  pos, j  =   0 ; i  <  S -> length  &&  j  <  T -> length; )
 {
     //  i是主串游標,j是模式串游標
      if  ( - 1   ==  j  ||                  //  模式串游標已經回退到第一個位置
         S -> str[i]  ==  T -> str[j])  //  當前字符匹配成功
      {
         //  滿足以上兩種情況時兩個游標都要向前進一步
          ++ i;
         ++ j;
    }
     else                          //   匹配不成功,模式串游標回退到當前字符的next值
      {
        j  =  next[j];
    }
}

free(next);

 if  (j  >=  T -> length)
 {
     //  匹配成功
      return  i  -  T -> length;
}
 else
  {
     //  匹配不成功
      return   - 1 ;
}

}/這就是最后的程序了 /</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!