字符串匹配基础
匹配所针对的目标是主串S与模式串P。
- BF算法
- RK算法
1. BF算法
BF是Brute Force算法的简写,理解起来就是暴力算法。通过滑动主串窗口,依次与模式串P比较的一个过程,遇到第一个不匹配即退出。时间复杂度为O(N*M),其中N为主串S的长度,M为模式串P的长度。
据说Java的IndexOf就是用的此法,简单符合KISS原则,且针对一般情况都是长主串,短字串的情况,比如N>>M,那么M可以忽略了。
如LeetCode 28题实现strStr()。
解法
func bf(s, p string) int {
n := len(s)
m := len(p)
if m < 1{
return 0
}
if m > n {
return -1
}
var i, j = 0, 0
for i < n && j < m {
if s[i] == p[j]{
i++
j++
} else {
// 不匹配的话,i就需要向右移动1,因为第一次s[i]和p[j]相等的时候,如果一直相等,i和j增长的是一样的,那么i回退到原来位置就是i-j,向右移动一位就是+1.
i = i - j + 1
// 不匹配p上的指针j就要重新回到0,
j= 0
}
}
if j == m { // 注意这里的等号,只有j匹配到了末尾,因为相等会导致j继续加1
return i-j
} else {
return -1
}
}
2. RK算法
RK是Rabin和Karp算法简写。这个算法与BF算法类似,只是它将BF算法中主串与字串的比对匹配过程,更换为Hash值比较。所以这里的hash值是重点,如何设计冲突小的hash算法,是本算法的重点。
如果全部是字母,可考虑使用26进制,进行计算hash啥的。
伪代码:
func rk(s, p string) int {
n := len(s)
m := len(p)
pH := hash(p)
for i:=0; i < n-m+1; i++ {
chidH := hash(s[i:i+m+1]) // 取s中i到i+m的子串的hash值
if childH == pH {
return i
}
}
}