关于字符串模式匹配算法的一点理解

  此贴最先是发布在CDOJ-BBS,现在觉得应该将这篇文章发布出来,让更多的人看见。与更多的朋友、大师们交流学习心得。

  对于以下提及的各种算法,学完后回过头来想想,觉得都是比较好实现的,主要是在于应用。不过我在最初学习这些算法的时候,每每学一个新算法总会有一种大脑一片茫然的感觉,不知从何入手,然后就去找一大堆资料,而我最后真正认真看了的估计就几篇,所以现在回想起来,学习新算法的时候只要找到一两篇文章认认真真地看上几遍应该就基本上差不多了,当然对于acm来说,看完之后就要多找几道题来练练手了。

BM(Boyer-Moore)算法
    BM算法思想很简单就是匹配的时候采用从右向左检查,匹配窗口依然从左向右滑动,在实际应用中会比kmp跑得快。 
    更多请点击这里:字符串匹配BM(Boyer-Moore)算法学习心得

kmp、e_kmp、还有z-算法(注:扩展kmp与z-box不是同一算法,具体实现方式上会有一点区别。
    关于两个kmp算法,我kmp算法学得比较久了,而扩展kmp算法相对学得较晚,这两个算法就比较短,大家模拟一下实现过程应该会对这两个算法会有更深的理解的。
    在后面提到的“呀啦那一卡”这套题里面有一道相当好的kmp的题,个人感觉题相当好,虽然感觉是难了点。但如果把这道题写了之后,我相信会对kmp有更加深刻的理解的。比较惭愧的是我现在已经基本忘了我那题是怎么写的了。

trie
    我对这玩意儿的理解就是一颗字典树,和模拟差不多。

Aho–Corasickautomaton
    AC automaton嘛,感觉上就是trie与kmp的合体,感觉两者实际上是同一个东西,只是kmp是单串的,ac automaton是多串的,思想是差不多的。
    对于ac automaton总结,个人觉得这个是比较好学的。trie大家肯定是能随便建的嘛,fail指针一加上就成了ac automaton了,还是比较方便的哈,不过我写的ac automaton代码是比较孬的那种,每次都要对root做一个特殊讨论的,后面发现如果加一个辅助结点,让这个结点的所有next指向root,root->fail指向这个结点,代码一下简洁多了,大家有兴趣的话可以去试试。
    ac automaton,我主要看到了两个版本,感觉都各有好处,一种是建完树以后,只建fail指针,不再对next做处理,我最开始就是写的这种方法,感觉还是不错的,另一种就是在建fail的时候还对每个结点的next也做一些相应的处理,这样写的话,在匹配的时候就会感觉特别方便,而且有些和dp、矩阵快乘相关的题上,这样写也会比较方便。不过感觉上初学的话还是第一种比较好。

    ac automaton 的话,还可以解决一个问题,那就是一个带有‘?’的模式串的问题,关于这个问题这里有详细讲解
HDU 3901 Wildcard AC自动机通配符匹配提醒:对于内存开得刚刚好的acmer,此题串长没有严格小于10^5,但小于10^5+11)

   个人感觉这一点,基本上打破了我一直以来对ac自动机的理解,我一直以为只有当要多串匹配时才需要ac自动机,而现在就算是单串,也可能需要ac自动机了。虽然实质上这里还是多串匹配,但至少从思维上来说,以后的思维宽度可能会更宽了,

关于以上部分:特别感谢——李凯镇——提供的相关资料

suffix arrays    后缀数组吧,学完后回想起来,感觉还是比较好学的,我基本就是靠看《后缀数组——处理字符串的有力工具》-罗穗骞—09这篇论文入门的,个人感觉讲得还是挻好的,虽然我当时看了很久才大概明白了一点倍增算法的思想,关于dc3完全不懂,
    我觉得这篇论文在后面给我练习相当好,给出了很后缀数组应用的例子,在使用了几次之后,也就基本明白后缀数组倍增算法了。
    在这里推荐一下昀昀放的一套题呀啦那一卡(字符串专题) http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=1496#overview ,这套题个人感觉相当不错的,对于匹配来说是很好的练习。个人对学了后缀数组的感觉就重在练习与使用上了。

suffix tree
    这个东西吧,我也是前不久才学的,只学了一点点,不过感觉上如果之前会后缀数组和ac自动机的话感觉上学起来好学一点,不过现在感觉上整个人是比较浮躁的。现在感觉自己想静下心来看点东西感觉比较困难的样子了。
    后缀树的话,我觉得这篇论文讲得还是比较不错的《On–line construction of suffix trees》,至少实现的代码比较短,我就是按里面写的伪代码实现的。不过由于各种原因,当时这篇论文我看了一周才基本明白suffix tree。
    好不容易学了suffix tree,去写fzu的(Problem 1916 Harmonious Substring Function——http://acm.fzu.edu.cn/problem.php?pid=1916)一把就MLE了。还需要多加学习啊。

RK
    RK实际上就是基于hash的,个人感觉RK还是很实用的,偶尔遇到一些比较难的题,用RK暴一暴居然就过了,太神了,不过RK的思想非常简单了,而且也是人人都能写的那种,如果在想不出一个复杂度比较好的算法时,可以用RK试试。
    关于RK还有几点:经常听见有人说单hash不靠谱,不过个人感觉这个比较靠人品吧,我一般就是单hash的,挂的次数还是比较少的,实在不行,换两个模数一般问题还是不大的。还有,关于hash之后的查找串,我记得有一次我把这个功能写成一个函数,然后就T了,后面看别人的代码,他把这个写在查找的那个地方,没有写成函数,我也这样改,然后就过了。以致于以后我都这样写,不过我总觉得这样是一个不好的习惯。大家看着办吧,RK如果T了的话,可以试试。
    最后,我想说我记得这个算法好像叫Karp-Rabin算法吧,为什么变成RK了而不是KR?

Manacher算法
    这个算法就使用面就比较窄了。
    在这里对这个算法做了一点讨论。
    http://acm.uestc.edu.cn/bbs/read.php?tid=3258
    不知道为什么,在我写这个的时候这篇贴子里的那个原网站打不开了~~
    关于这个算法还有一点我个人觉得比较好玩,有的人把这个算法写作hw(回文)+…算法,然后我看到就囧了。
    关于这个算法,还找到了另外一个版本,感觉各种神啊!还没看懂其中原理。
    http://acm.hust.edu.cn:8080/judge/problem/viewSource.action?id=123100

    写完这篇贴子之后突然发现我写的东西太没有营养了。看来我情商还是太低了一点。
    不过也算明白了一个问题,为什喵代码要用英文敲?因为中文敲得太慢了。

     最后推荐大家两个网站吧,个人感觉还是相当不错的叫 演算法笔记 我也不知道为什么要叫演算法。我每次去这个网站总要用google翻译成简体中文看,是不是觉得我太弱了一点呢?我总觉得繁体字一大坨,看着好累啊~~
    http://www.csie.ntnu.edu.tw/~u91029/
    还有一个英文的,感觉也很不错的样子
    http://www.allisons.org/ll/AlgDS/

点赞