字符串匹配算法--BF、KMP、Sunday

字符串匹配算法

1、字符串相关的算法很多,今天总结的是字符串匹配算法,之前已知的有两种算法,一种叫做BF(Brute Force)算法,也就是蛮力算法,就是匹配串和模式串左对齐,不匹配则模式串向右移一个单位,直到匹配或结束,这中间有很多无用的匹配,特别是对匹配串中有重复字符串出现的时候;第二种就是第一种方法的改进,叫做KMP算法,此算法晦涩难懂,但归根结底就两句话,一是找出匹配串的next数组,二是不匹配时的移动规则。BF算法比较简单,此不详述,下面给出了KMP算法,已在VS2005上调试通过。

//Contact是一个类——联系人,匹配的是电话号码

void KMP(Contact &c, string partStr)

{

if (partStr.length() <= 0)

return;

int * next = new int[partStr.length()];

if (NULL == next)

return;

findNext(next, partStr);

string tmpStr = partStr;

unsigned int str_i=0;

for (unsigned int phone_i=0; phone_i < c.getPhone().length() && str_i < tmpStr.length(); )

{

if (c.getPhone()[phone_i] != tmpStr[str_i])

{

if (next[str_i] >= 0)

{

str_i = next[str_i];

}

else if (-1 == next[str_i])

{

str_i = 0;

++phone_i;

}

}

else

{

++phone_i;

++str_i;

}

}

if (str_i == tmpStr.length())

cout<<c.getName()<<"    "<<c.getPhone()<<endl;

}

//对于匹配串每个元素对应的next数组中的值是其前面字符串前缀等于后缀的最大长度。

//如“ababcd”,字符’c’的next数组对应的值大小为2.

void findNext(int next[], string partStr)

{

if(NULL == next || partStr.length() <= 0)

return;

for(unsigned int i = 0; i < partStr.length(); ++i)

{

if(0 == i)

next[i] = -1;

else if(1 == i)

next[i] = 0;

else

{

for(unsigned int back = 1; back < i; ++back)

{

unsigned int front = 0, count=0, tmpBack = back;

next[i] = 0;

while(partStr[front] == partStr[tmpBack] && tmpBack < i)

{

++front;

++tmpBack;

++count;

}

if(tmpBack == i)

{

next[i] = count;

break;

}

}

}

}

在这里引申一下,前几天在一家国内著名互联网公司的笔试中出现了一道次方法的变种,如果不匹配,则要找到最大可匹配的长度,在这里只简单说下思想,比如模式串为“abcde”,如果没有完全匹配的,可记下最大匹配长度,注意这里是从首字符开始匹配的,也就是任意长度可匹配的字符串均从首字符开始,如最大为3,则是“abc”;然后模式串变为“bcde”,此时还需要重新算next数组,再次匹配,也是从首字符开始匹配的,也就是任意长度可匹配的字符串均从首字符开始,如最大为3,则是“bcd”;依次下去,找到最大的可匹配长度。


3、下面介绍一种更高效的算法:Sunday算法。Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配。其核心思想是:在匹配过程中,模式串发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。

如匹配串“stay student studying”、模式串“study”,如下图,第一个第二个匹配,第三个不匹配,那么匹配串中哪个字符一定会在下次匹配中出现呢,是模式串末尾’y’对应’s’后面的’t’,此时我们需要寻找’t’在模式串中是否出现,结果模式串中存在’t’,相匹配。

stay student studying

study

我们发现在最后一个字符不匹配,e-y不匹配,此时需要找’n’是否在study出现,结果没有,继续往后,’t’出现了,相匹配。

stay student studying

        study

我们发现首字符不匹配,s-n不匹配,此时需要找’d’是否出现在模式串中,找到了。

stay student studying

    study

将’d’对齐,我们此时便找到了匹配的字符串,是不是很快。

stay student studying

        study

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值