给定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) } }