字符串匹配算法问题小记

匹配算法

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就去掉了换行符。

当然还有其他方法,这里仅针对该问题提出了针对性修正。

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