kmp算法及改进

一、failture版
int pmatch(char *string,char *pat)
{
    int i=0,j=0;
    int lens=strlen(string);//主字符串
    int lenp=strlen(pat);//需要匹配的字符串
    while(i < lens && j < lenp)
    {
        if(string[i]==pat[j])//如果顺利匹配,下标都移动
        {
            i++;
            j++;
        }
        else if(j==0)//如果需要匹配的字符串首字母都不匹配,主串移动下标
            i++;
        else //都不是的情况
            j=failure[j-1]+1;
    }
    return ((j==lenp) ? (i-lenp):-1);//返回的是主串匹配的首元素下标
}

void fail(char *pat)
{
    int n=strlen(pat);
    failure[0]=-1;
    int i,j;
    for( j=1;j<n;j++)
    {
        i=failure[j-1];
        while((pat[j]!=pat[i+1]) && (i >= 0))//检测需要匹配的串是否有重复的部分
            i = failure[i];
        if(pat[j] == pat[i+1])//如果有重复,记住位置,当匹配出错,就将需要匹配字符串的下标移动到前面重复出现的字母的下标(下面的例子)
            failure[j] = i+1;
        else 
            failure[j] = -1;
    }
}
            a  b  c  a  b  c  a  c  a  b
failture    -1 -1 -1 0  1  2  3  -1 0  1

二、nextval版(kmp改进)
#include<stdio.h>
#include<string.h>
void get_nextval(char *T,int *nextval)
{
    int i,j;
    i=1;
    j=0;
    nextval[0]=0;
    while(i<strlen(T))
    {
        if(j==0|| T[i]==T[j])
        {

            if(T[i]!=T[j])//和未改进算法一样
                nextval[i]=j;
            else 
                nextval[i]=nextval[j];//改进就是把之前出现过的都表示一个地方
            ++i;
            ++j;
        }
        else 
            j=nextval[j];
    }
}

int Index_KMP(char *S,char *T,int pos)
{
    int i=pos;//可以实现任意开始位置匹配

    int j=0;
    int len1=strlen(S);
    int len2=strlen(T);
    int next[255]={0};

    get_nextval(T,next);
    while(i<len1&&j<len2)
    {
        if(j==0||S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else 
            j=next[j];
    }
    if(j>=len2)
        return i-len2;
    else 
        return -1;

}
int main()
{
    char *a="aaabbaaabbb";
    char *b="aaabbb";
    printf("%d\n",Index_KMP(a,b,0));//从头开始匹配

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值