第一行两个整数 n , m (1<=m<=n<=50000),第二行为长度为n且只包含’a’和’b’的字符串s。
输出在操作次数不超过 m 的情况下,能够得到的 最大连续 全’a’子串或全’b’子串的长度。
8 1 aabaabaa
5
把第一个 'b' 或者第二个 'b' 置成 'a',可得到长度为 5 的全 'a' 子串。
官方题解的GO版本
package main import( "fmt" "bufio" "os" ) func main() { var n, m int fmt.Scan(&n) fmt.Scan(&m) reader := bufio.NewReaderSize(os.Stdin, n) line, _, _ := reader.ReadLine() // fmt.Println(max(arraySolve(n, m, line, 'a'), arraySolve(n, m, line, 'b'))) fmt.Println(windowSolve(line, m, n)) } func arraySolve(n, m int, s []byte, c byte) int { res := 0 indexes := make([]int, 0) //存储所有的a/b字符的下标 for i := 0; i < n; i++ { if s[i] == c { indexes = append(indexes, i) } } // 全部替换即可 if len(indexes) <= m { return n } // 在最后面补一位,防止漏掉最后一个连续子串的情形 indexes = append(indexes, n) // indexes[m]表示前面刚好有m个a/b,将它们全部替换掉得到的子串长度res即为indexes[m]指向的下标 res = indexes[m] for i := m+1; i < len(indexes); i++ { // indexes[i] 与 indexes[i-m-1]之间共有m+1个a/b,而indexes[i-m-1]本身就是a/b,因此再减去1,就可以得到最长子串 res = max(res, indexes[i]-indexes[i-m-1]-1) } return res } func windowSolve(str []byte, m, n int) int { var res int left, right := 0, 0 cntA, cntB := 0, 0 for right < n { if str[right] == 'a' { cntA++ } else { cntB++ } if cntA > m && cntB > m { res = max(res, right-left) if str[left] == 'a' { cntA-- } else { cntB-- } left++ } right++ } res = max(res, right-left) return res } func max(a, b int) int { if a > b { return a } return b }