Skip to main content

符合条件的子串

By 2022-05-08算法

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

 

Leave a Reply