今天的题,难如老狗
28. 找出字符串中第一个匹配项的下标
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
示例 1:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
示例 2:
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
KMP,看一次,忘一次,学一次,忘一次,抄就完事。
/*
func strStr(haystack string, needle string) int {
for i:=0;i+ len(needle)<=len(haystack);i++{
flag:=true
for j:=0;j<len(needle);j++{
if haystack[i+j]!= needle[j]{
flag = false
break //加不加都行,剪枝
}
}
if flag{return i}
}
return -1
}
*/
func NextArr(next [] int, s string){
j:=-1
next[0] = -1
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//前两步都是调整j,next[i] ,就是将调整好的j放到对应的i下标中,存储这个前缀关系
}
//遍历结束,每一个i都得到由j维护好的前缀
}
func strStr(haystack string,needle string)int{
if len(needle) == 0{ return 0 }
next:=make([]int,len(needle))//构造next前缀数组
NextArr(next,needle)
j:=-1
for i:=0;i<len(haystack);i++{
for j>=0 && haystack[i]!= needle[j+1]{ j = next[j]}//如果前缀不等,就让j保持之前的前缀 aab 因为b不等,所以令j = aa
if haystack[i] == needle[j+1]{ j++ }//如果相等,就将j增加1
if j== len(needle)-1{ return i-len(needle)+1}//j的长度等于 模式串的长度,就已经完成匹配
}
return -1
}
459. 重复的子字符串
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
示例 2:
输入: s = "aba"
输出: false
示例 3:
输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)
思路:难如老狗
/*
func repeatedSubstringPattern(s string) bool {
n:=len(s)
for i:=1; i*2<=n; i++{ //计算一般即可
if n%i == 0{ //成倍数关系
match := true
for j:=i; j<n; j++{ //子串长度
if s[j]!=s[j-i]{
match =false
break
}
}
if match{ return true }
}
}
return false
}
*/
func repeatedSubstringPattern(s string) bool {
return kmp(s + s, s)
}
func kmp(query, pattern string) bool {
n, m := len(query), len(pattern)
fail := make([]int, m)
for i := 0; i < m; i++ {
fail[i] = -1
}
for i := 1; i < m; i++ {
j := fail[i - 1]
for j != -1 && pattern[j + 1] != pattern[i] {
j = fail[j]
}
if pattern[j + 1] == pattern[i] {
fail[i] = j + 1
}
}
match := -1
for i := 1; i < n - 1; i++ {
for match != -1 && pattern[match + 1] != query[i] {
match = fail[match]
}
if pattern[match + 1] == query[i] {
match++
if match == m - 1 {
return true
}
}
}
return false
}