给定m个不重复的字符 [a, b, c, d],以及一个长度为n的字符串tbcacbdata,问能否在这个字符串中找到一个长度为m的连续子串,使得这个子串刚好由上面m个字符组成,顺序无所谓,返回任意满足条件的一个子串的起始位置,未找到返回-1。比如上面这个例子,acbd,3。
package main
import "fmt"
func main(){
printOutput(find([]byte{'a','b','d'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
printOutput(find([]byte{'a','b','d', 'c'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
printOutput(find([]byte{'t','b','c'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
printOutput(find([]byte{'t'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
printOutput(find([]byte{'c','b','a'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
printOutput(find([]byte{'t','a'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
printOutput(find([]byte{'g'}, []byte{'t','b','c','a','c','b','d','a','t','a'}))
}
func find(a, b []byte) (int, string) {
mapping := map[byte]bool{}
// init
for _, n := range a {
mapping[n] = true
}
i := 0 // 窗口左
for j := 0; j < len(b); j++ { // 窗口右
v, ok := mapping[b[j]] // 窗口往右扩
if ok && v{ // 如果在m中且当前字母【未】被占用
// 正常扩充窗口右直到达到目标size
mapping[b[j]] = false // 标记占用
if j - i + 1 == len(a) { // 退出条件:窗口大小与m相同
return i, string(b[i: j + 1])
}
} else if ok && !v { // 如果在m中且当前字母被占用(如cac)
// 更新窗口左至该已被占用的字母前一次出现的后一个位置
if _, okk := mapping[b[i]]; okk {
for i <= j {
if b[i] != b[j] {
mapping[b[i]] = true
i++
} else {
break
}
}
i++
}
} else { // 如果不在m中
// 更新窗口左至窗口右处,且将所过之处恢复原状
for i <= j {
if _, okk := mapping[b[i]]; okk {
mapping[b[i]] = true
}
i++
}
}
}
return -1, ""
}
func printOutput(pos int, str string){
if pos == -1 {
fmt.Printf("string not found\n")
} else {
fmt.Printf("start at pos: %d, string is: %s\n", pos, str)
}
}