C语言 字符串匹配问题,KMP函数-失配函数

有两个字符串,一个为str,一个为pat。
我们的目的是查找pat在str中出现的位置。

最简单的办法无非就是两层循环。

for(int i=0; i<strlen(str); i++)
{
    for(int j=0; j<strlen(pat); j++)
    {
        if(str[i+j] != pat[j]
            break;
    }
    if(j < strlen(pat))
        break;
    else
        index = i;    //index保存str中pat子串出现的首位置
}
if(i < strlen(str))
    printf("Match success!The index is:%d",index);
else
    printf("Match failed");

以上这个算法虽然简单,但是效率不高。
我们需要一个更高效的算法

我们先来看一个例子,

char *str = “abcaccabcabcac”;
char *pat= “abcabcac”;

我们先按照最简单的算法走。
设定匹配到str中的位置为i,匹配到pat中的位置为j;
当我们匹配到 i=4,j=4的时候。

已经不能匹配了,这时候我们就需要将i+1,而j又要从0开始。
当然,这样是完全可以得到正确的结果的。

但是,当我们仔细观察pat的时候发现。当我们接下来用i=5和j进行匹配的时候,我们可以直接和j=1进行匹配,而不用进行j=0时候的匹配。

因为我们的pat子串中的pat[0]~pat[3]和pat[3]~pat[6]是相同的。

这样我们就不必去比较j=0的情况。

这就意味着,如果在pat中是一个满足一定条件的子串,我们就不用每次都将j从第0个位置开始匹配,而是可以根据一些规律,有选择的选择j的位置。

定义:模式串P=p(0)p(1)……p(n-1)的失配函数定义如下:
若存在p(0)p(1)……p(i) = p(j-i)p(j-i+1)……p(j), i小于j;
f(j) = max{i,0};
否则,f(j) = -1;

例如模式串P = ‘a b c a b c a c a b’, 失配函数是

j     0   1   2   3   4   5   6   7   8   9
P     a   b   c   a   b   c   a   c   a   b
f(j)  -1  -1  -1  0   1   2   3   -1  0   1

有了失配函数,我们很容易得到一个规则

如果部分匹配结果是s(i-j)……s(i-1) = p(0)p(1)……p(j-1)且si 不等于 pj。
则接下来如果 j 不等于0,应该用 si 与p( f(i-1)+1 )相比,如果j = 0,应该用p(0)与s(i+1)相比。

下面是程序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define M 101

//失配函数 
void fun(char *arr, int res[])
{
    res[0] = -1;
    for(int i=1; i<strlen(arr); i++)
    {
        int j=0;

        if(arr[i] != arr[j])
        {
            res[i] = -1;
        }
        else
        {
            while(arr[i] == arr[j] && i<strlen(arr))
            {
                res[i] = j;
                i++;
                j++;
            }
            i--;
        }
    }
}

int main()
{
    char str[M],pat[M];
    int f[M];
    int i=0,j=0;

    gets(str);
    gets(pat);

    fun(pat,f);

    while(i < strlen(str) && j < strlen(pat))
    {
        if(str[i] == pat[j])
        {
            i++;
            j++;
        }
        else if(j == 0)
            i++;
        else
            j = f[j-1] + 1;
    }

    if(j == strlen(pat))
        printf("Match success!\n The %s is in %s at %d",pat,str,i-strlen(pat));
    else
        puts("Match failed!");
}
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/wang545593725/article/details/51285099
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞