滑动窗口之 RABIN KARP 字符匹配算法

187. 重复的DNA序列

28. 找出字符串中第一个匹配项的下标

 

对于字符串匹配算法,一般可以通过「暴力」「KMP 算法」来解决。今天介绍一种基于滑动窗口的 RABIN KARP 字符匹配算法

关于滑动窗口的详细总结可见 滑动窗口技巧

引入

现在给定一个纯数字的字符串s = "9876",如何把它转化成数字呢?

那么如何去掉上面字符串的最高位呢?

下面介绍的 RABIN KARP 字符匹配算法就是基于这个原理!!

重复的DNA序列

题目详情可见 重复的DNA序列

这个题目大家肯定可以想到暴力的方法:

暴力的时间复杂度为:O(NL),其中L是每次截取字符串的耗时

我们能不能想办法把这个L给去掉呢????这样时间复杂度就直接是O(N)

'A', 'C', 'G','T'映射成0, 1, 2, 3四个数字,所以字符串ACGT就变成了数0123

比较两个字符串是否相等,只需要比较对应的数是否相等即可!换句话来说,就是把比较字符串换成了比较字符串的 Hash 值

滑动窗口算法本身的时间复杂度是O(N),再看看窗口滑动的过程中的操作耗时,给ans添加子串的过程用到了substring方法需要O(L)的复杂度,但一般情况下substring方法不会调用很多次,只有极端情况 (比如字符串全都是相同的字符) 下才会每次滑动窗口时都调用substring方法

所以我们可以说这个算法一般情况下的平均时间复杂度是O(N),极端情况下的时间复杂度会退化成O(NL)

找出字符串中第一个匹配项的下标

题目详情可见 找出字符串中第一个匹配项的下标

这个题目大家肯定也可以想到暴力的方法:(和上一题暴力的方法大同小异)

这个题目也可以使用上面介绍的方法,但不同的点在于,本题的字符集比较大

虽然题目中说是只有小写英文字母,但是我们权当包含了整个 ASCII 码的集合,即有 256 位,相当于是 256 进制

所以问题就很明显了,无论用什么类型来存,肯定会溢出,这个时候「模运算」就可以大显身手了!!

使用「模运算」就会存在冲突的问题,我们从两个方面来解决这个问题: