字符串匹配算法問題小記

匹配算法

Brute Force算法

BF算法也叫樸素模式匹配算法,是由Bruce Force提出來的,算法基本思想就是簡單粗暴的一次比較的問題。算法的C代碼實現很簡單,但是在操作中遇到了一些細節問題。
問題代碼

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define LEN 100

int B_FIndex(char S[],char T[])
{
    int i = 0,j = 0;
    int Len_S = strlen(S); // 使用strlen函數獲取字符串長度
    int Len_T = strlen(T);

    if(S == NULL || T == NULL || Len_S < Len_T)     // Error Input
        return -1;

    while(i < Len_S && j < Len_T)
    {
        if(S[i] == T[j])
        {
            i++;
            j++;
        }// end if
        else
        {
            i = i - j +1;
            j = 0;
        }// end else
    }//end while

    if(j >=Len_T)
    {
        printf("Success patterened at %d",i-j);	// 匹配成功位置信息提示
        return 0;
    }
    else
    {
        printf("Fail patterened");
        return -1;
    }
}//end BF

int main(int argc,char * argv[])
{
    char S[LEN+1],T[LEN+1];

    fgets(S,sizeof(S),stdin);	// 採用推薦的安全函數fgets
    fgets(T,sizeof(T),stdin);

    B_FIndex(S,T);
}

這段代碼初看沒什麼問題,與其他博客的代碼沒什麼差別,編譯也能順利通過,但是卻無法100%正確匹配,爲什麼這麼說?
case1:子串=主串

hello world
hello world
Success patterened at 0
Process returned 0 (0x0)   execution time : 16.536 s
Press any key to continue.

能正確輸出期望值。
case2:子串<主串

hello world
hello
Fail patterened
Process returned 0 (0x0)   execution time : 9.249 s
Press any key to continue.

這是什麼原因造成的?
由於scanf()函數只能接收連續的字符串,遇到空格便結束,對匹配的功能有所影響,所以選擇了fgets()函數(比gets()函數更安全、通用)。
如果我們直接換用gets()函數在一般的應用中是沒有問題的,上述代碼可以正常工作。但是gets()函數的最大問題在於它不檢查輸入是否超過了數組長度,這將引起內存溢出的安全問題。
真正造成問題的原因在與fgets()與gets()的另一個差別上:

  • gets()逐個讀入字符,指導讀到換行符是停止(丟棄換行符)
  • fgets()也是逐個讀入字符,直到遇到首個換行符或已經讀入了sizeof(str)-1個字符時結束操作。如果讀入了換行符,那麼它會把換行符和其他字符一起保存

所以關鍵就是換行符的問題。
在case1的情況下,主串字符爲

h e l l o w o r l d ‘\n’ ‘\0’

字串也爲

h e l l o w o r l d ‘\n’ ‘\0’

所以匹配成功沒問題。
但是在case2下,字串爲

h e l l o ‘\n’ ‘\0’

所以就造成了去匹配時子串是帶上換行符一起去進行匹配。

以上就是問題分析了,解決方法就是在BF函數中求字符串長度時吧這個換行符減掉,修改的關鍵代碼如下

    int Len_S = strlen(S) - 1; // 使用strlen函數獲取字符串長度,不包含結束符,
    int Len_T = strlen(T) - 1; // 減1就去掉了換行符。

當然還有其他方法,這裏僅針對該問題提出了針對性修正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章