第一行两个整数 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
}