我的水平所限,只能谈及几年前的OI省选水平的算法。再高深的,便不清楚了。html
主要参考文献:git
OI算法,大抵可分为如下几类:github
下面依次谈一谈。算法
这个算法是怎么来的,是为了解决什么问题而来,之前的算法为何没有解决,而如今的算法却能解决;如今这个算法还有些什么缺点;能作一些什么问题,不能作些什么问题。—— Ronghua Li数组
KMP:在主串S(长度N)中匹配一个模式串P(长度M),预处理时间 O(M) ,匹配时间 O(N+M) 。数据结构
KMP及相关算法时间复杂度比较:函数
其中,M为模式串长度,N为主串长度。 实测时,string长度10000,每一个函数都被调用了1000次。
算法 | 预处理时间 | 匹配时间 | 实测时间 |
---|---|---|---|
BF | O(0) | O(NM) | 0.078 |
KMP | O(M) | O(N) | 0.094 |
BM | O(N+M2) | O(N) | 0.047 |
Sunday | O(M) | O(NM) | 0.172 |
Robin-Karp | O(0) | O(NM) | 0.328 |
Bitap | O(M) | O(NM)→O(N) | 0.281 |
Trie是一种n叉树,n为字母表大小,每一个节点表示从根节点到此节点所通过的全部字符组成的字符串。工具
AC自动机就是KMP思想。但用KMP作多模式串匹配的时间复杂度是 O(∑N+Mi) 。显然,提升的复杂度是 O(N(K−1)) ,其中K表示模式串的个数。而当模式串数量大、模式串较短、主串较长时,算法几乎是从 O(N2) 降到了 O(N) 。ui
还有一种多模式的匹配算法叫作AC自动机。它能一次匹配多个模式串。它与KMP的思路很像,不匹配时找一个最长的再继续进行!它须要先把字符串建成一颗Trie树,树结点有一个叫作failed的指针,是表示若是不匹配时应该再从哪一个结点进行匹配。由于这种作法是一种DFA上的匹配,而发明这种算法的人叫A.C.,因此就叫AC自动机了。复杂度很好,比每一个模式串用一次KMP算法要好不少。atom
还有一种叫作后缀数组和后缀树的,后缀树是能够转发为后缀数组的,这两种构造起来很不简单,可是复杂度倒是惊人的好。如求最长重复连续子串,出现次数最多的子串等都能用它完美的解决。有兴趣的能够搜搜,后缀数组的资料应该是比较多的,然后缀树因为太复杂,资料不是不少,仍是有的。
关于后缀数组构造的倍增算法,有一个特别好玩的小故事,你们能够去看看~
《后缀树,后缀数组,离散化》,去看73到81页,可爱的小白兔们^_^
上面介绍的都是精确匹配的算法,其实对于字符串,还有一种模糊匹配,有兴趣的读者能够阅读一本叫作《柔性字符串匹配》的书,确定会让你获益匪浅。