由字符串匹配到KMP算法

字符串匹配问题就是在指对于两段字符串,待匹配串和模式串,寻找待匹配串中模式串是否出现,及出现的位置。
例如在文本编辑中,我们经常要在一段文本中某个特定的位置找出某个特定的字符或模式。


1、简单字符串匹配(BF-Brute Force算法)
这个算法简单粗暴,就是从左边对齐一个个字符对比,相同就对比下一位,不同的话模式串就整体右移一位,再一个个字符对比,直到右边对齐~

int match(string& target, string& pattern)
{
    int target_length = target.size();
    int pattern_length = pattern.size();
    int target_index = 0;
    int pattern_index = 0;
    while(target_index < target_length && pattern_index < pattern_length){
    //如果pattern遍历到最后一位则找到,target遍历到最后一位代表没找到,都要跳出循环。
        if(target[target_index]==pattern[pattern_index]){
            ++target_index;
            ++pattern_index;
        }
        else{//出现了不匹配,模式串index回到第一个字符,出现了几次不匹配,待匹配串index就是几啦~
            target_index -= (pattern_index-1); 
            pattern_index = 0;
        }
    }
    if(pattern_index == pattern_length)//pattern遍历到了最后一位
        return target_index - pattern_length;
    else//target遍历到了最后一位
        return -1;
}

算法复杂度是O(target_length*pattern_length)~~

2、STL字符串匹配函数~~string::
find():在一个字符串中查找一个指定的单个字符或字符数组。如果找到,就返回首次匹配的开始位置;如果没有查找到匹配的内容,就返回string::npos。
find_first_of():在一个目标串中进行查找,返回值是第一个与指定字符组中任何字符匹配的字符位置。如果没有查找到匹配的内容,则返回npos。
find_last_of():在一个目标串中进行查找,返回最后一个与指定字符组中任何字符匹配的字符位置。如果没有查找到匹配的内容,则返回npos。
rfind():对一个串从尾至头查找一个指定的单个字符或字符组。如果找到,就返回首次匹配的开始位置;如果没有查找到匹配的内容,则返回npos。
find(string, int):第一个参数用来指示要查找的字符,第二个参数用来表示从字符串的何处开始查找子串(默认的查找位置是0)。


3、KMP算法
第一步中的简单匹配算法可用下图来表示~遇到不匹配就从头开始重新匹配,index代表移动的位数~
这里写图片描述
很明显会发现,从0到1这一步是多余的,因为target的第一位和pattern的第一位相匹配而与第二位显然不匹配,这一步我们在index=0时已经做了,所以如果将已经匹配了部分的字符串分析一下,再决定移动多少位会大大降低复杂度。
假设对于pattern中的部分已匹配字符串这里写图片描述

存在最大的k,使0~k的字符串与j-k~j的字符串相同,我们称为最大公共前后缀。比如在index=0的匹配中,k=2,pattern右移(5(已匹配字符串字符数)-3(最大公共前后缀数))位。这样的移位可最大程度地使(与后缀相同)前缀覆盖已匹配的后缀,移位后前缀将不需要在进行匹配,整个优化后的过程如下图所示~

所以整个KMP算法的核心在于,如何计算K

这里写代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值