KMP算法解析

一、简介

KMP 算法是用来求一个较长字符串是否包含另一个较短字符串的算法,其中难点在于求解 next 数组。

二、next 数组含义

next 数组含义为:如果匹配到该字符时失败,回溯的位置。

strabaabcac
pos01234567
next-10011201

其中,next 数组首位设置为-1,意味着首位匹配失败时无法回溯。

三、next 数组求解

代码示例

string str = "abaabcac";
vector <int> next(str.size(), -1);

for (int i = 0, j = -1; i < next.size()-1; )
{
	if (j==-1 || str[i]==str[j])
		next[++i] = ++j;
	else
		j = next[j];
}

算法思想

从数组首地址开始遍历,判断以下情况:

  • 如果 j 为 -1 , 意味此次若匹配失败时,必须回溯到串首 str[0] 开始匹配,在 next 数组下一位置中记下该值,接下来可以继续判断 str 字符串后置位。

  • 如果 j 不为 -1 ,且匹配至 str[j] 成功,则此次若匹配失败从 j+1 开始匹配,在 next 数组下一位置中记下该值,接下来可以继续判断 str 字符串后置位。

  • 如果 j 不为 -1 ,且匹配至 str[j] 失败,则找到 str[j] 位置匹配失败回溯位置,即令 j=next[j] 求得该回溯位置,并再次进行判断。此时意味着将 str[i] 位置字符替换 str[j] 位置字符,重新计算回溯。

如此,直到 next 数组被填满。

其中 j 起时值设置为 -1 ,是认为 str 首位匹配即失败,并避免 str[0]==str[0] 。

四、KMP 算法

代码示例

class Solution {
public:
    int strStr(string haystack, string needle) {
        if (needle.size() == 0)
            return 0;
        if (haystack.size() == 0)
            return -1;
        
        vector <int> next(needle.size(), -1);
        for (int i = 0, j = -1; i < next.size()-1; )
        {
            if (j==-1 || needle[i]==needle[j])
                next[++i] = ++j;
            else
                j = next[j];
        }
        
        for (int i = 0, j = 0; i < haystack.size(); )
        {
            if (j==-1 || haystack[i]==needle[j])
                i++, j++;
            else
                j = next[j];
            
            if (j == needle.size())
                return i-j;  
        }
        
        return -1;
    }
};

算法思想

从首位置遍历 haystack 字符,判断是否匹配:

  • 如果匹配,则后移 haystack 字符指针和 needle 字符指针,继续判断是否匹配。

  • 如果不匹配,固定 haystack 字符指针不变,根据 next 数组移动 needle 字符指针。

直到遍历完 haystack 字符串(即失败)或者匹配到 needle 字符串末尾(即成功)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值