字符匹配KMP算法

KMP是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的。其中第一位就是《计算机程序设计艺术》的作者!!

KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。就是我们平时常说的关键字搜索。模式串就是关键字(接下来称它为T),如果它在一个主串(接下来称为S)中出现,就返回它的具体位置,否则返回-1.

KMP算法的核心就是避免不必要的回溯,不必要的回溯可以后模式串决定。KMP算法为模式串添加一个next数组用来指导模式匹配串下一步改用第几号元素进行匹配。next数组举例:

T9ababaaaba
下标0123456789
nextX011234223

假设prefix表示当前下标字符的后缀,suffix表示当前下标字符的前缀,我们关注的是前缀和后缀的相同字符数,由此来决定next数组。至于前缀后缀可通过下面步骤自己体会,文字感觉说不清楚。

T串第0个字符表示T串长度,对于next[0]=X,

当T[1]字符发生失配,此时next[1]=0;    当T[2]字符发生失配,此时next[2]=1

当T[3]字符发生失配,此时prefix=‘a’,suffix='b',且前缀后缀不相等,此时next[3]=1

当T[4]字符发生失配,此时prefix='a',suffix='a',且前缀后缀有一个相等,此时next[4]=2

当T[5]字符发生失配,此时prefix='a''b',suffix=‘a’'b',且前缀后缀有两个相等,此时next[5]=3

当T[6]字符发生失配,此时prefix='a''b''a',suffix='a''b''a',且前缀后缀有三个相等,此时next[6]=4

当T[7]字符发生失配,此时prefix='a',suffix=‘a’,且前缀后缀有一个相等,此时next[7]=2

当T[8]字符发生失配,此时prefix='a',suffix=‘a’,且前缀后缀有一个相等,此时next[8]=2

当T[9]字符发生失配,此时prefix='a''b',suffix='a''b',且前缀后缀有两个相等,此时next[9]=3

以后为next数组的获取过程,代码如下:

void next(String T,int *next)
{
    prefix = 0;
    suffix = 1;
    next[1] = 0;
    
    while(suffix < T[0])
    {
        if(0 == prefix || T[suffix] == T[prefix])
        {
            suffix++;
            prefix++;
            next[suffix] = prefix;
        }
        else
        {
            prefix = next[prefix];
        }
    }
}

返回子串T在主串S第pos个字符之后的位置,若不存在,返回-1

#include <stdio.h>

typedef char* String;

void next(String T, int *next)
{
    int j = 0;
	int i = 1;
	next[1] = 0;

	while( i < T[0] )
	{
		if( 0 == j || T[i] == T[j] )
		{
			i++;
			j++;
			next[i] = j;
		}
		else
		{
			j = next[j];
		}
	}
}

int Index(String S, String T, int pos)
{
    int i = pos;
    int j = 1;
    int next[255];

    next(T, next);

    while(i < S[0] && j <= T[0])
    {
        if(0 == j || S[i] == T[j])
        {
            i++;
            j++;
            if(T[i] != T[j])
                next[i] = j;
            else
                next[i] = next[j];
        }
        else
        {
            j = next[j];
        }
    }

    if(j > T[0])
        return i - T[0];
    else
        return -1;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值