-
28实现strSTR
- 代码随想录 (programmercarl.com)
-
第一印象
- 暴力的方法是遍历haystack,每遇到needle的开头就进行一次比对,复杂度为O(n^2)
-
讲解中关于KMP的重要点
- 前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
- 前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。
- 后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。
- 匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面重新匹配就可以了。
- 前缀表中模式串与前缀表对应位置的数字表示的是:下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀
-
解题代码
- 前缀表使用-1实现
-
/ 方法一:前缀表使用减1实现
func getNext(next []int, s string) {
j := -1
next[0] = j
for i := 1; i < len(s); i++ {
for j >= 0 && s[i] != s[j+1] {
j = next[j]
}
if s[i] == s[j+1] {
j++
}
next[i] = j
}
}
func strStr(haystack string, needle string) int {
if len(needle) == 0 {
return 0
}
next := make([]int, len(needle))
getNext(next, needle)
j := -1
for i := 0; i < len(haystack); i++ {
for j >= 0 && haystack[i] != needle[j+1] {
j = next[j]
}
if haystack[i] == needle[j+1] {
j++
}
if j == len(needle)-1 {
return i - len(needle) + 1
}
}
return -1
}
- 前缀表直接实现
-
func getNext(next []int, s string) {
j := 0
next[0] = j
for i := 1; i < len(s); i++ {
for j > 0 && s[i] != s[j] {
j = next[j-1]
}
if s[i] == s[j] {
j++
}
next[i] = j
}
}
func strStr(haystack string, needle string) int {
n := len(needle)
if n == 0 {
return 0
}
j := 0
next := make([]int, n)
getNext(next, needle)
for i := 0; i < len(haystack); i++ {
for j > 0 && haystack[i] != needle[j] {
j = next[j-1]
}
if haystack[i] == needle[j] {
j++
}
if j == n {
return i - n + 1
}
}
return -1
}
-
459重复的子字符串
- 代码随想录 (programmercarl.com)
-
解题思路
- (一)如果字符串可以由其中包含的一个子字符串重复得到。那么将原本的字符串复制一份连接到本身的后面,那么新得到的二倍长度的字符串内部一定至少有一个不同于前一半和后一半的和原字符串相同的部分。
- (二)也可以利用KMP算法求字符串的next数组,如果next最后的值大于0,且其与数组长度的差可以被原字符串长度整除,那么成立。
-
解题代码
- 不减一
-
func repeatedSubstringPattern(s string) bool {
len := len(s)
if len < 2 {
return false
}
next := make([]int,len)
getNext(next, s)
if next[len-1]!=0 && len%(len - next[len-1])==0 {
return true
}
return false
}
func getNext(next []int, s string) {
j := 0
next[0] = j
for i:=1;i<len(s);i++ {
for j>0 && s[i] != s[j] {
j = next[j-1]
}
if s[i] == s[j] {
j++
}
next[i] = j
}
}
- 减一
-
func repeatedSubstringPattern(s string) bool {
n := len(s)
if n == 0 {
return false
}
next := make([]int, n)
j := -1
next[0] = j
for i := 1; i < n; i++ {
for j >= 0 && s[i] != s[j+1] {
j = next[j]
}
if s[i] == s[j+1] {
j++
}
next[i] = j
}
if next[n-1] != -1 && n%(n-(next[n-1]+1)) == 0 {
return true
}
return false
}