关闭

关于字符串算法的总结

319人阅读 评论(0) 收藏 举报
分类:

趁着做presentation的时候,顺便把自己最近学习的几种常用字符匹配算法藤上博客和大家分享下。。有什么不懂的地方,可以指出相互交流

  首先是KMP算法。

这个算法实在是太有名了,大学上的算法课程除了最笨的Brute Force 算法,然后就介绍了KMP 算法。也难怪,呵呵。谁让Knuth D.E. 这么world famous 呢,不仅拿了图灵奖,而且还写出了计算机界的Bible <The Art of Computer Programming>这个算法是算法书上一般都有的。在此也就不赘述了。

  当然,有市场就有竞争,字符串匹配这么大一个市场,不可能让BF 和KMP 全部占了,于是又出现了几个强劲的对手。

Horspool算法
Boyer-Moore算法 
Sunday算法
RK算法
下面简要介绍下这几个主要算法的思想:

Horspool 算法的思想很简单的。不过有个创新之处就是模式串是从右向左进行比较的。很好很强大,为后来的算法影响很大。
匹配串:abcbc sdccdab

模式串:cbcac
这个时候我们从右向左进行对暗号,c-c ,恩对上了,第二个b-a ,不对啊,我们应该怎么办?难道就这么放弃么。于是,模式串从不匹配的那个字符开始从右向左寻找匹配串中不匹配的字符b 的位置

匹配串:abcbcsdccdab
模式串: cbcac
这个算法的效率还比较高,不过最坏情况下不如kmp的

第二个上来的是Boyer-Moore 算法。
是一个很复杂的算法,当然,虽然理论上时间复杂度和KMP 差不多,但是实际上却比KMP 快数倍,可见实践是检验真理的唯一标准。

分为两步预处理,第一个是bad-character heuristics ,也就是当出现错误匹配的时候,移位,基本上就是做的Horspool 那几个操作
第二个就是good-suffix heuristics ,当出现错误匹配的时候,我还要从不匹配点向左看啊,以前匹配的那段子字符串是不是在模式串本身中还有重复的啊,有重复的话,那么我就直接把重复的那段和匹配串中已经匹配的那一段对齐

其实第二条规则和kmp有点相似,都做了子字符串的预处理,要用数组保存。
演示
匹配串:abaccba bbazz
模式串:cbadcba

匹配串:abaccbabbaz z
模式串:    cbadcba
然后有时候我们会发现:
匹配串:abacccb bbazz
模式串:cbadccb
这种情况是只有部分匹配的,所以

匹配串:abacccbbbazz
模式串:         cbadccb

最后一个是Sunday 算法,实际上比Boyer-Moore 还快,呵呵。长江后浪推前浪。
思想也更简单。
Sunday 的算法思想和Horspool 有些相似,但是。当出现不匹配的时候,却不是去找匹配串中不匹配的字符在模式串的位置,而是直接找最右边对齐的右一位的那个字符在模式串的位置。

比如:
匹配串:abcbc zdxzc
模式串:zbcac

这里我们看到b-a 没有对上,我们就看匹配串中的z 在模式串的位置,然后,嘿嘿。
匹配串:abcbczdxzc
模式串:          zbcac
如果模式串中的没有那个字符怎么办呢?很简单,跳过去呗

在串匹配的简单算法中,把文本每m个字符构成的字符段作为一个字段,和模式进行匹配检查。如果能对一个长度为m的字符
串赋以一个Hash函数。那么显然只有那些与模式具有相同hash函数值的文本中的字符串才有可能与模式匹配,这是必要条件
   用这个思想就是我们的RK算法了。我挺喜欢的。

事实上,之前的串匹配方法,是将模式串的一个一个字符作为小的特征去分别进行匹配,而RK算法则是将串整体作为一个
特征!难就难在单个字符的特征很容易想得到,整体作为一个特征就没那么容易想得到了。。。貌似和我们之前学的聚类分析有点异曲同工之妙。

用这个思想可以设计有针对性的匹配代码。
我举个简单的例子、
把字符串看做一个26进制数
然后由于可能模式串太长,不能用一个数表示,我们就会想到用hash,用一个大质数取模,只有匹配串中取模后的值和模式串一样才进行比较。。

所以匹配串需要进行一次预处理,进行取模运算,保存在一个新的数组。预处理的具体实现的方法有点巧妙的,用到一点数论的知识。有兴趣的可以去研究下。

ps,需要说明的是strstr是c语言提供的字符串匹配函数,而他使用Brute Force实现的,此处看出有时候暴力法并不一定就那么差,并且简单易懂。

上面的都是些思想,至于算法实现还是要有一些trick的,大家可以自己Google

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:9305次
    • 积分:150
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:6篇
    • 译文:0篇
    • 评论:0条