KMP算法(字符串的匹配)

一、BF算法(朴素算法)

缺点:每次失配都是从头重新开始,效率低下

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

int main()
{
    char s[]="abcdefgab";
    char t[]="abcdef";

    int a,b;
    int i=0,j=0;

    a=strlen(s);
    b=strlen(t);
    j=0;

    printf(" 请输入数i,代表从主串s哪个位置开始\n");
    scanf("%d",&i);

    while(j<b&&i<a)
    {
        if(s[i]==t[j])
        {
            i++;
            j++;
        }
        else
        {
            i=i-j+2;
            j=1;
        }
    }
    if(j>=b)
    printf("匹配成功");
    else
    printf("匹配失败"); 
    return 0;   
}
//0 匹配成功
//其他数 匹配失败 

二、kmp算法(效率高)

1.KMP算法的关键在于使用next数组
2.next数组作用:当模式匹配串T(子串)失配时,next数组对应的元素指导应该用T串哪个元素进行下一轮的匹配(就是失配时,后缀的next值所对应的位置的next的值当做下一轮匹配的位置

三、前后缀怎么看

1.若子串是 a,b,a,c

在c处失配,看第一个和c的前一位=>相同都是a
一位相同则c的next为2=>用自己2号去与目标串匹配

2.若子串是 a,b,a,b,a,c

在c处失配,最前面三位和除c的后三位相同
三位相同,c的next为4=>用自己的4号位与目标串匹配

3.若在1号位就失配

next=0 =>自己的0号去配

四、得到next功能函数

//前缀是固定的,后缀是相对的
void o_next(String T,int *next)//o_next函数里只需要子串T,建立指针next是为了传数组next
{
    int j=0;//j是前缀
    int i=1;//i是后缀
    next[1]=0;//这是恒定的

    while(i<T.length)
    {
        if(0==j||T.str[i]==T.str[j])//o==j是刚开始让它进入用的
        {
            i++;
            j++;
            next[i]=j;
        }
        else
        {
            j=next[j];//next的作用,告诉这一次到哪一位置去匹配
        }
    }
}

《KMP算法(字符串的匹配)》

五、KMP算法源码

/************************************************************************* > File Name: kmp.c > Author: geeker > Mail: 932834897@qq.com > Created Time: 2017年02月23日 星期四 14时11分34秒 ************************************************************************/

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

typedef struct
{
    int length;//存字符串长度
    char *str;//存字符串
}String;//若无法理解String的在前面的博客有解释

//前缀是固定的,后缀是相对的
void o_next(String T,int *next)
{
    int j=0;//j是前缀
    int i=1;//i是后缀
    next[1]=0;//这是恒定的

    while(i<T.length)
    {
        if(0==j||T.str[i]==T.str[j])//o==j是刚开始让它进入用的
        {
            i++;
            j++;
            next[i]=j;
        }
        else
        {
            j=next[j];//next的作用,告诉这一次到哪一位置去匹配
        }
    }
}

//kmp函数最后返回子串T在主串S第pos个字符的位置
//若不存在,返回0
int kmp(String S,String T,int pos)//pos是需要从哪里开始寻找的位置
{
    int i=pos;//开始索引的位置
    int j=1;
    int next[255];//最多存放255

    o_next(T,next);//模式匹配串不用去管S串是怎么样的

    while(i<=S.length&&j<=T.length)//条件,前后缀都要小于字符串长度
    {
        if(0==j||S.str[i]==T.str[j])//必须要0==j,否则会出现next引用越界,也是为了让第一下能进去
        {
            i++;
            j++;
        }
        else
        {
            j=next[j];
        }
    }
    if(j>T.length)//匹配成功,返回匹配的位置
    {
        return i-T.length;
    }
    else
    {
        return 0;
    }
}


int main()
{
    String S,T;
    char *str=" ababaaaba";
    S.str=str;//主字符串的赋值
    S.length=strlen(str)-1;//排除串前的空格符 ???

    char *str1=" baa";
    T.str=str1;//子字符串的赋值
    T.length=strlen(str1)-1;
    int k;
    k=kmp(S,T,0);//传入S,T字符串,并从0开始匹配

    if(0==k)
    {
        printf("匹配失败\n");
    }
    else
    {
        printf("匹配成功了,匹配点为%d\n",k);
    }

    //最后显示S串中next数组里的值
    int next[255];
    o_next(S,next);
    printf("S=ababaaaba,T=baa的next数组为:\n");
    for(int i=1;i<=S.length;i++)
    {
        printf("%d ",next[i]);
    }
    printf("\n");
    return 0;
}

效果图
《KMP算法(字符串的匹配)》

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/w_linux/article/details/56674198
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞