import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _676C extends CodeForcesApp {
  override def apply(io: IO) = {
    val (n, k, s) = io[(Int, Int, String)]

    val pas, pbs = Array.ofDim[Int](n + 1)
    s.indices foreach {i =>
      pas(i + 1) = pas(i) + (s(i) == 'a').to[Int]
      pbs(i + 1) = pbs(i) + (s(i) == 'b').to[Int]
    }

    def isOk(l: Int, r: Int) = pas(r) - pas(l) <= k || pbs(r) - pbs(l) <= k
    val ans = twoPointer(n + 1)(isOk).map{case (x, y) => y - x}

    io += ans.max
  }

  def twoPointer(n: Int)(f: (Int, Int) => Boolean): Vector[(Int, Int)] = {
    def run(l: Int, r: Int): Vector[(Int, Int)] = r match {
      case `n` => Vector.empty
      case _ if f(l, r) => run(l, r + 1) :+ (l -> r)
      case _ => if (l < r) run(l + 1, r) else run(l, r + 1)
    }
    run(0, 0)
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = t.head.ensuring(t.size == 1)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_._1).mapValues(_._2)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_._1).mapValues(_.map(_._2).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f) findWithIndex c
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    def bitCount: Int = java.lang.Long.bitCount(x)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(n.min(x, y), n.max(x, y), n.one)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: V): Dict[K, V] = Dict.empty[K, V] withDefaultValue default // also to(Dict.empty[K2, V])
  }
  def memoize[A, B](f: A => B): collection.Map[A, B] = new mutable.HashMap[A, B]() {
    override def apply(key: A) = getOrElseUpdate(key, f(key))
  }
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) Some(f) else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends PrintWriter(out, true) with Iterator[String] {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def apply[A](implicit read: IO.Read[A]): A = read.apply(this)
  def apply[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(apply).to[C]

  def till(delim: String): String = tokenizer().get.nextToken(delim)
  def tillEndOfLine(): String = till("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  var separator = " "
  private[this] var isNewLine = true

  def +=[A](x: A)(implicit write: IO.Write[A]): this.type = {
    write(this)(x)
    this
  }
  def ++=[A: IO.Write](xs: Traversable[A]): this.type = (this += xs.size) appendNewLine xs

  def appendNewLine[A: IO.Write](x: A): this.type = {
    println()
    this += x
  }

  override def print(obj: String) = {
    if (isNewLine) isNewLine = false else super.print(separator)
    super.print(obj)
  }
  override def println() = if (!isNewLine) {
    super.println()
    isNewLine = true
  }
  override def close() = {
    flush()
    in.close()
    super.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r[C, A](r[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val boolean                                      : Read[Boolean]      = string.map(_.toBoolean)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r[A], r[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r[A], r[B], r[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r[A], r[B], r[C], r[D]))
  }
  trait Write[-A] {
    def apply(out: PrintWriter)(x: A): Unit
  }
  trait DefaultWrite {
    implicit def any[A]: Write[A] = Write(_.toString)
  }
  object Write extends DefaultWrite {
    def apply[A](f: A => String) = new Write[A] {
      override def apply(out: PrintWriter)(x: A) = out.print(f(x))
    }
    implicit val boolean: Write[Boolean] = Write(b => if (b) "YES" else "NO")
    implicit def tuple2[A, B]: Write[(A, B)] = Write {case (a, b) => s"$a $b"}
    implicit def array[A]: Write[Array[A]] = Write(_ mkString " ")
    implicit def iterable[A](implicit write: Write[A]): Write[Traversable[A]] = new Write[Traversable[A]] {
      override def apply(out: PrintWriter)(xs: Traversable[A]) = {
        xs foreach write(out)
        out.println()
      }
    }
  }
}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, k) = in.next().split(' ').map(_.toInt)
  val line = in.next()
  val (at, _, _, bt, _, _) = line.indices.foldLeft((0, 0, k, 0, 0, k)) {
    case (att@(amax, acurrent, aleft, bmax, bcurrent, bleft), i) =>
//      println(att)
      val ch = line(i)
//      println(ch)
      if (ch == 'a') {
        if (bleft > 0)
          (Math.max(amax, acurrent + 1), acurrent + 1, aleft, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft - 1)
        else {
          var ni = bcurrent
          while (ni > 0 && line(i - ni) != 'a')
            ni -= 1
//          println("ni " + ni)
          if (ni > 0)
            (Math.max(amax, acurrent + 1), acurrent + 1, aleft, Math.max(bmax, ni), ni, bleft)
          else
            (Math.max(amax, acurrent + 1), acurrent + 1, aleft, bmax, 0, k)
        }
      }
      else {
        if (aleft > 0)
          (Math.max(amax, acurrent + 1), acurrent + 1, aleft - 1, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft)
        else {
//          println("acurrent " + acurrent)
//          println("i = " + i)
          var ni = acurrent
          while (ni > 0 && line(i - ni) != 'b')
            ni -= 1
//          println("NI a " + ni)

          if (ni > 0)
            (Math.max(amax, ni), ni, aleft, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft)
          else
            (amax, 0, k, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft)
        }
      }
  }
  println(Math.max(at, bt))
}

object C676 {

  import IO._
  import collection.{mutable => cu}

  def main(args: Array[String]): Unit = {
    val Array(n, k) = readInts(2)
    val str = read
    val charCountA = Array.fill(n+1)(0)
    val charCountB = Array.fill(n+1)(0)
    for(i <- 1 to n) {
      charCountA(i) = charCountA(i-1)
      charCountB(i) = charCountB(i-1)

      if(str(i-1) == 'a')
        charCountA(i) += 1
      else
        charCountB(i) += 1
    }

    var res = 0

    def lastOccuranceOrLowerBinarySearch(arr: Array[Int], i: Int, target: Int): Int = {
      var low = i+1
      var high = n

      while(low < high) {
        val mid = low + (high-low+1)/2

        if(arr(mid) > target) {
          high = mid - 1
        } else {
          low = mid
        }
      }
      low
    }

    for(i <- 0 until n) {
//      println(i, lastOccuranceOrLowerBinarySearch(charCountA, i, charCountA(i) + k), lastOccuranceOrLowerBinarySearch(charCountB, i, charCountB(i) + k))
      val last = math.max(
        lastOccuranceOrLowerBinarySearch(charCountA, i, charCountA(i) + k),
        lastOccuranceOrLowerBinarySearch(charCountB, i, charCountB(i) + k)
      )

      res = math.max(res, last-i)
    }

    out.println(res)

    out.close()
  }

  object IO {
    private val input = new java.io.BufferedReader(new java.io.InputStreamReader(System.in))
    //    private val input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream("src/input")))
    val out = new java.io.PrintWriter(System.out)

    @inline def read: String = input.readLine()

    @inline def tokenizeLine = new java.util.StringTokenizer(read)

    def readInt: Int = tokenizeLine.nextToken.toInt

    def readInts(n: Int): Array[Int] = {
      val tl = tokenizeLine
      Array.fill(n)(tl.nextToken.toInt)
    }

    def readLongs(n: Int): Array[Long] = {
      val tl = tokenizeLine
      Array.fill(n)(tl.nextToken.toLong)
    }

    def readBigs(n: Int): Array[BigInt] = {
      val tl = tokenizeLine
      Array.fill(n)(BigInt(tl.nextToken))
    }
  }

}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _676C extends CodeForcesApp {
  override def apply(io: IO) = {
    val (n, k, s) = io[(Int, Int, String)]

    val pas, pbs = Array.ofDim[Int](n + 1)
    s.indices foreach {i =>
      pas(i + 1) = pas(i) + (s(i) == 'a').to[Int]
      pbs(i + 1) = pbs(i) + (s(i) == 'b').to[Int]
    }

    def solve(l: Int, r: Int): Int = if (r <= n) {
      if(pas(r) - pas(l) <= k || pbs(r) - pbs(l) <= k) {
        solve(l, r + 1) max (r - l)
      } else {
        solve(l + 1, r)
      }
    } else {
      0
    }

    io += solve(0, 0)
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = t.head.ensuring(t.size == 1)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
    def prefixSum(implicit n: Numeric[A]) = t.scanLeft(n.zero) {case (acc, i) => n.plus(acc, i)}
    def suffixSum(implicit n: Numeric[A]) = t.scanRight(n.zero) {case (i, acc) => n.plus(acc, i)}
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_._1).mapValues(_._2)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_._1).mapValues(_.map(_._2).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class SortedExtensions[A, C[A] <: collection.SortedSet[A]](val s: C[A]) extends AnyVal {
    def greaterThanOrEqualTo(a: A): Option[A] = s.from(a).headOption
    def lessThan(a: A): Option[A] = s.until(a).lastOption
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f) findWithIndex c
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    def bitCount: Int = java.lang.Long.bitCount(x)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def absDiff(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(n.min(x, y), n.max(x, y), n.one)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: V): Dict[K, V] = Dict.empty[K, V] withDefaultValue default // also to(Dict.empty[K2, V])
  }
  def memoize[A, B](f: A => B): collection.Map[A, B] = new mutable.HashMap[A, B]() {
    override def apply(key: A) = getOrElseUpdate(key, f(key))
  }
  implicit class FuzzyDouble(x: Double)(implicit eps: Double = 1e-9) {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x absDiff y) <= eps
  }
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) Some(f) else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  val mod: Int = (1e9 + 7).toInt
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends PrintWriter(out, true) with Iterator[String] {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def apply[A](implicit read: IO.Read[A]): A = read.apply(this)
  def apply[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(apply).to[C]

  def till(delim: String): String = tokenizer().get.nextToken(delim)
  def tillEndOfLine(): String = till("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  var separator = " "
  private[this] var isNewLine = true

  def +=[A](x: A)(implicit write: IO.Write[A]): this.type = {
    write(this)(x)
    this
  }
  def ++=[A: IO.Write](xs: Traversable[A]): this.type = (this += xs.size) appendNewLine xs

  def appendNewLine[A: IO.Write](x: A): this.type = {
    println()
    this += x
  }

  override def print(obj: String) = {
    if (isNewLine) isNewLine = false else super.print(separator)
    super.print(obj)
  }
  override def println() = if (!isNewLine) {
    super.println()
    isNewLine = true
  }
  override def close() = {
    flush()
    in.close()
    super.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r[C, A](r[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val boolean                                      : Read[Boolean]      = string.map(_.toBoolean)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r[A], r[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r[A], r[B], r[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r[A], r[B], r[C], r[D]))
  }
  trait Write[-A] {
    def apply(out: PrintWriter)(x: A): Unit
  }
  trait DefaultWrite {
    implicit def any[A]: Write[A] = Write(_.toString)
  }
  object Write extends DefaultWrite {
    def apply[A](f: A => String) = new Write[A] {
      override def apply(out: PrintWriter)(x: A) = out.print(f(x))
    }
    implicit val boolean: Write[Boolean] = Write(b => if (b) "YES" else "NO")
    implicit def tuple2[A, B]: Write[(A, B)] = Write {case (a, b) => s"$a $b"}
    implicit def array[A]: Write[Array[A]] = Write(_ mkString " ")
    implicit def iterable[A](implicit write: Write[A]): Write[Traversable[A]] = new Write[Traversable[A]] {
      override def apply(out: PrintWriter)(xs: Traversable[A]) = {
        xs foreach write(out)
        out.println()
      }
    }
  }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _676C extends CodeForcesApp {
  override def apply(io: IO) = {
    val (n, k, s) = io[(Int, Int, String)]

    val pas, pbs = Array.ofDim[Int](n + 1)

    s.indices foreach {i =>
      if (s(i) == 'a') {
        pas(i + 1) = pas(i) + 1
        pbs(i + 1) = pbs(i)
      } else {
        pas(i + 1) = pas(i)
        pbs(i + 1) = pbs(i) + 1
      }
    }

    var ans = 0

    @tailrec
    def solve(l: Int, r: Int): Unit = if (r <= n) {
      if(pas(r) - pas(l) <= k || pbs(r) - pbs(l) <= k) {
        ans = ans max (r - l)
        solve(l, r + 1)
      } else {
        solve(l + 1, r)
      }
    }

    solve(0, 0)

    io += ans
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = t.head.ensuring(t.size == 1)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
    def prefixSum(implicit n: Numeric[A]) = t.scanLeft(n.zero) {case (acc, i) => n.plus(acc, i)}
    def suffixSum(implicit n: Numeric[A]) = t.scanRight(n.zero) {case (i, acc) => n.plus(acc, i)}
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_._1).mapValues(_._2)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_._1).mapValues(_.map(_._2).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class SortedExtensions[A, C[A] <: collection.SortedSet[A]](val s: C[A]) extends AnyVal {
    def greaterThanOrEqualTo(a: A): Option[A] = s.from(a).headOption
    def lessThan(a: A): Option[A] = s.until(a).lastOption
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f) findWithIndex c
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    def bitCount: Int = java.lang.Long.bitCount(x)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def absDiff(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(n.min(x, y), n.max(x, y), n.one)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: V): Dict[K, V] = Dict.empty[K, V] withDefaultValue default // also to(Dict.empty[K2, V])
  }
  def memoize[A, B](f: A => B): collection.Map[A, B] = new mutable.HashMap[A, B]() {
    override def apply(key: A) = getOrElseUpdate(key, f(key))
  }
  implicit class FuzzyDouble(x: Double)(implicit eps: Double = 1e-9) {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x absDiff y) <= eps
  }
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) Some(f) else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  val mod: Int = (1e9 + 7).toInt
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends PrintWriter(out, true) with Iterator[String] {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def apply[A](implicit read: IO.Read[A]): A = read.apply(this)
  def apply[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(apply).to[C]

  def till(delim: String): String = tokenizer().get.nextToken(delim)
  def tillEndOfLine(): String = till("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  var separator = " "
  private[this] var isNewLine = true

  def +=[A](x: A)(implicit write: IO.Write[A]): this.type = {
    write(this)(x)
    this
  }
  def ++=[A: IO.Write](xs: Traversable[A]): this.type = (this += xs.size) appendNewLine xs

  def appendNewLine[A: IO.Write](x: A): this.type = {
    println()
    this += x
  }

  override def print(obj: String) = {
    if (isNewLine) isNewLine = false else super.print(separator)
    super.print(obj)
  }
  override def println() = if (!isNewLine) {
    super.println()
    isNewLine = true
  }
  override def close() = {
    flush()
    in.close()
    super.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r[C, A](r[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val boolean                                      : Read[Boolean]      = string.map(_.toBoolean)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r[A], r[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r[A], r[B], r[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r[A], r[B], r[C], r[D]))
  }
  trait Write[-A] {
    def apply(out: PrintWriter)(x: A): Unit
  }
  trait DefaultWrite {
    implicit def any[A]: Write[A] = Write(_.toString)
  }
  object Write extends DefaultWrite {
    def apply[A](f: A => String) = new Write[A] {
      override def apply(out: PrintWriter)(x: A) = out.print(f(x))
    }
    implicit val boolean: Write[Boolean] = Write(b => if (b) "YES" else "NO")
    implicit def tuple2[A, B]: Write[(A, B)] = Write {case (a, b) => s"$a $b"}
    implicit def array[A]: Write[Array[A]] = Write(_ mkString " ")
    implicit def iterable[A](implicit write: Write[A]): Write[Traversable[A]] = new Write[Traversable[A]] {
      override def apply(out: PrintWriter)(xs: Traversable[A]) = {
        xs foreach write(out)
        out.println()
      }
    }
  }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _676C extends CodeForcesApp {
  override def apply(io: IO) = {
    val (n, k, s) = io[(Int, Int, String)]

    val pas, pbs = Array.ofDim[Int](n + 1)
    s.indices foreach {i =>
      pas(i + 1) = pas(i) + (s(i) == 'a').to[Int]
      pbs(i + 1) = pbs(i) + (s(i) == 'b').to[Int]
    }

    def solve(l: Int, r: Int): Option[Int] = {
      when(pas(r) - pas(l) <= k || pbs(r) - pbs(l) <= k) {
        r - l
      }
    }

    io += twoPointer(n + 1)(solve).get
  }

  def twoPointer[A: Ordering](n: Int)(f: (Int, Int) => Option[A]): Option[A] = {
    def run(l: Int, r: Int): Option[A] = if(r == n) {
      None
    } else {
      f(l, r) match {
        case None if l < r => run(l + 1, r)
        case v => (run(l, r + 1) ++ v).whenNonEmpty(_.max)
      }
    }
    run(0, 0)
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = t.head.ensuring(t.size == 1)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_._1).mapValues(_._2)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_._1).mapValues(_.map(_._2).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f) findWithIndex c
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    def bitCount: Int = java.lang.Long.bitCount(x)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(n.min(x, y), n.max(x, y), n.one)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: V): Dict[K, V] = Dict.empty[K, V] withDefaultValue default // also to(Dict.empty[K2, V])
  }
  def memoize[A, B](f: A => B): collection.Map[A, B] = new mutable.HashMap[A, B]() {
    override def apply(key: A) = getOrElseUpdate(key, f(key))
  }
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) Some(f) else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends PrintWriter(out, true) with Iterator[String] {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def apply[A](implicit read: IO.Read[A]): A = read.apply(this)
  def apply[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(apply).to[C]

  def till(delim: String): String = tokenizer().get.nextToken(delim)
  def tillEndOfLine(): String = till("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  var separator = " "
  private[this] var isNewLine = true

  def +=[A](x: A)(implicit write: IO.Write[A]): this.type = {
    write(this)(x)
    this
  }
  def ++=[A: IO.Write](xs: Traversable[A]): this.type = (this += xs.size) appendNewLine xs

  def appendNewLine[A: IO.Write](x: A): this.type = {
    println()
    this += x
  }

  override def print(obj: String) = {
    if (isNewLine) isNewLine = false else super.print(separator)
    super.print(obj)
  }
  override def println() = if (!isNewLine) {
    super.println()
    isNewLine = true
  }
  override def close() = {
    flush()
    in.close()
    super.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r[C, A](r[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val boolean                                      : Read[Boolean]      = string.map(_.toBoolean)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r[A], r[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r[A], r[B], r[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r[A], r[B], r[C], r[D]))
  }
  trait Write[-A] {
    def apply(out: PrintWriter)(x: A): Unit
  }
  trait DefaultWrite {
    implicit def any[A]: Write[A] = Write(_.toString)
  }
  object Write extends DefaultWrite {
    def apply[A](f: A => String) = new Write[A] {
      override def apply(out: PrintWriter)(x: A) = out.print(f(x))
    }
    implicit val boolean: Write[Boolean] = Write(b => if (b) "YES" else "NO")
    implicit def tuple2[A, B]: Write[(A, B)] = Write {case (a, b) => s"$a $b"}
    implicit def array[A]: Write[Array[A]] = Write(_ mkString " ")
    implicit def iterable[A](implicit write: Write[A]): Write[Traversable[A]] = new Write[Traversable[A]] {
      override def apply(out: PrintWriter)(xs: Traversable[A]) = {
        xs foreach write(out)
        out.println()
      }
    }
  }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _676C extends CodeForcesApp {
  override def apply(io: IO) = {
    val (n, k, s) = io[(Int, Int, String)]

    val pas, pbs = Array.ofDim[Int](n + 1)
    s.indices foreach {i =>
      pas(i + 1) = pas(i) + (s(i) == 'a').to[Int]
      pbs(i + 1) = pbs(i) + (s(i) == 'b').to[Int]
    }

    def isOk(l: Int, r: Int) = pas(r) - pas(l) <= k || pbs(r) - pbs(l) <= k
    val ans = twoPointer(n + 1)(isOk).maxBy{case (x, y) => y - x}

    io += (ans._2 - ans._1)
  }

  /**
    * Two pointer algorithm
    * O(2*n)
    *
    * @param n
    * @param f
    *          f must be monotonic i.e. j is a super-interval of i then f(j) => f(i)
    *                             anf also if !f(i) then for all
    * @return
    *         List of all intervals in [0, n) at which f is defined
    */
  def twoPointer(n: Int)(f: (Int, Int) => Boolean): Vector[(Int, Int)] = {
    def run(l: Int, r: Int): Vector[(Int, Int)] = if (r == n) {
      Vector.empty
    } else if (f(l, r)) {
      run(l, r + 1) :+ (l -> r)
    } else if (l < r) {
      run(l + 1, r)
    } else {
      run(l, r + 1)
    }
    run(0, 0)
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = t.head.ensuring(t.size == 1)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_._1).mapValues(_._2)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_._1).mapValues(_.map(_._2).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f) findWithIndex c
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    def bitCount: Int = java.lang.Long.bitCount(x)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(n.min(x, y), n.max(x, y), n.one)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: V): Dict[K, V] = Dict.empty[K, V] withDefaultValue default // also to(Dict.empty[K2, V])
  }
  def memoize[A, B](f: A => B): collection.Map[A, B] = new mutable.HashMap[A, B]() {
    override def apply(key: A) = getOrElseUpdate(key, f(key))
  }
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) Some(f) else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends PrintWriter(out, true) with Iterator[String] {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def apply[A](implicit read: IO.Read[A]): A = read.apply(this)
  def apply[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(apply).to[C]

  def till(delim: String): String = tokenizer().get.nextToken(delim)
  def tillEndOfLine(): String = till("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  var separator = " "
  private[this] var isNewLine = true

  def +=[A](x: A)(implicit write: IO.Write[A]): this.type = {
    write(this)(x)
    this
  }
  def ++=[A: IO.Write](xs: Traversable[A]): this.type = (this += xs.size) appendNewLine xs

  def appendNewLine[A: IO.Write](x: A): this.type = {
    println()
    this += x
  }

  override def print(obj: String) = {
    if (isNewLine) isNewLine = false else super.print(separator)
    super.print(obj)
  }
  override def println() = if (!isNewLine) {
    super.println()
    isNewLine = true
  }
  override def close() = {
    flush()
    in.close()
    super.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r[C, A](r[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val boolean                                      : Read[Boolean]      = string.map(_.toBoolean)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r[A], r[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r[A], r[B], r[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r[A], r[B], r[C], r[D]))
  }
  trait Write[-A] {
    def apply(out: PrintWriter)(x: A): Unit
  }
  trait DefaultWrite {
    implicit def any[A]: Write[A] = Write(_.toString)
  }
  object Write extends DefaultWrite {
    def apply[A](f: A => String) = new Write[A] {
      override def apply(out: PrintWriter)(x: A) = out.print(f(x))
    }
    implicit val boolean: Write[Boolean] = Write(b => if (b) "YES" else "NO")
    implicit def tuple2[A, B]: Write[(A, B)] = Write {case (a, b) => s"$a $b"}
    implicit def array[A]: Write[Array[A]] = Write(_ mkString " ")
    implicit def iterable[A](implicit write: Write[A]): Write[Traversable[A]] = new Write[Traversable[A]] {
      override def apply(out: PrintWriter)(xs: Traversable[A]) = {
        xs foreach write(out)
        out.println()
      }
    }
  }
}

import Utils._, annotation.tailrec, collection.mutable, util._, control._, math.Ordering.Implicits._

object _676C extends CodeForcesApp {
  override def apply(io: IO) = {
    val (n, k, s) = io[(Int, Int, String)]

    val pas, pbs = Array.ofDim[Int](n + 1)
    s.indices foreach {i =>
      pas(i + 1) = pas(i) + (s(i) == 'a').to[Int]
      pbs(i + 1) = pbs(i) + (s(i) == 'b').to[Int]
    }

    def isOk(l: Int, r: Int) = pas(r) - pas(l) <= k || pbs(r) - pbs(l) <= k
    val Some((l, r)) = twoPointer(n + 1)(isOk)

    io += r - l
  }

  def twoPointer(n: Int)(f: (Int, Int) => Boolean): Option[(Int, Int)] = {
    def run(l: Int, r: Int): Option[(Int, Int)] = if(r == n) {
      None
    } else {
      val isValid = f(l, r)
      if (!isValid && l < r) {
        run(l + 1, r)
      } else {
        (run(l, r + 1) ++ when(isValid)(l -> r)).whenNonEmpty(_.maxBy { case (x, y) => y - x })
      }
    }
    run(0, 0)
  }
}
/****************************[Ignore Template Below]****************************************/
trait CodeForcesApp {
  lazy val isOnlineJudge: Boolean = sys.props.get("ONLINE_JUDGE").exists(_.toBoolean)
  def debug(x: Any): Unit = if (!isOnlineJudge) println(x)
  def apply(io: IO): io.type
  def main(args: Array[String]): Unit = this(new IO(System.in, System.out)).close()
}
object Utils {
  import scala.collection.mutable, mutable.{Map => Dict}
  implicit class GenericExtensions[A](val a: A) extends AnyVal {
    def partialMatch[B](f: PartialFunction[A, B]): Option[B] = f lift a
  }
  implicit class TraversableExtensions[A, C[X] <: Traversable[X]](val t: C[A]) extends AnyVal {
    def onlyElement: A = t.head.ensuring(t.size == 1)
    def groupByIdentifier[K](f: A => K): Map[K, A] = t.groupBy(f).mapValues(_.onlyElement)
    def duplicates(implicit b: C of A): C[A] = {
      val elems = mutable.Set.empty[A]
      (t collect {case i if !elems.add(i) => i}).to[C]
    }
    def sumWith[B](f: A => B)(implicit n: Numeric[B]): B = t.foldLeft(n.zero) {case (p, i) => n.plus(p, f(i))}
    def zipWith[B](f: A => B)(implicit b: C of (A, B)): C[(A, B)] = (t map {i => i -> f(i)}).to[C]
    def mapTo[B](f: A => B)(implicit b: C of (A, B)): Map[A, B] = zipWith(f).toUniqueMap
    def whenNonEmpty[B](f: t.type => B): Option[B] = when(t.nonEmpty)(f(t))  // e.g. grades.whenNonEmpty(_.max)
    def collectFirst[B](f: PartialFunction[A, Option[B]]): Option[B] = t.view collect f collectFirst {case Some(x) => x}
    def toMutableMultiSet: Dict[A, Int] = {
      val c = map[A] to 0
      t.foreach(i => c(i) += 1)
      c
    }
    def toMultiSet: Map[A, Int] = toMutableMultiSet.toMap withDefaultValue 0
  }
  implicit class ArrayExtensions[A <: AnyRef](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = java.util.Arrays.sort(a, from, until, cmp) //sort [from, until)
  }
  implicit class ArrayExtensions2[A](val a: Array[A]) extends AnyVal {
    def sort(from: Int, until: Int)(implicit cmp: Ordering[A]): Unit = a.view(from, until).sorted.copyToArray(a, from)
  }
  implicit class SeqExtensions[A, C[X] <: Seq[X]](val s: C[A]) extends AnyVal {
    def isRotationOf(t: Seq[A]): Boolean = s ++ s containsSlice t
  }
  implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) {
    def toUniqueMap: Map[A, B] = t.groupByIdentifier(_._1).mapValues(_._2)
    def toMultiMap(implicit b: C of B): Map[A, C[B]] = t.groupBy(_._1).mapValues(_.map(_._2).to[C])
    def swap(implicit b: C of (B, A)): C[(B, A)] = t.map(_.swap).to[C]
  }
  implicit class MapExtensions[K, V, C[X, Y] <: Map[X, Y]](val m: C[K, V]) extends AnyVal {
    def invert: Map[V, Set[K]] = m.toSet[(K, V)].swap.toMultiMap
    def mapKeys[K2](f: K => K2): Map[K2, V] = m map {case (k, v) => f(k) -> v}
    def toMutable: Dict[K, V] = Dict.empty[K, V] ++ m
  }
  implicit class SetExtensions[A, C[A] <: Set[A]](val s: C[A]) extends AnyVal {
    def notContains(x: A): Boolean = !(s contains x)
    def toMutable = mutable.Set.empty[A] ++ s
  }
  implicit class IterableExtensions[A, C[A] <: Seq[A]](val s: C[A]) extends AnyVal {
    def findWithIndex(f: A => Boolean): Option[(A, Int)] = s.zipWithIndex find {case (a, _) => f(a)}
    def foldUntil[B](z: B)(f: (B, A) => B)(c: B => Boolean): Option[(B, Int)] = s.view.scanLeft(z)(f) findWithIndex c
  }
  implicit class BooleanExtensions(val x: Boolean) extends AnyVal {
    def to[A](implicit n: Numeric[A]) = if(x) n.one else n.zero
  }
  implicit class LongExtensions(val x: Long) extends AnyVal {
    def bitCount: Int = java.lang.Long.bitCount(x)
  }
  implicit class NumericExtensions[A](val x: A)(implicit n: Numeric[A]) {
    import Numeric.Implicits._
    def **(i: Int): A = if (i == 0) n.one else {
      val h = x ** (i/2)
      if (i%2 == 0) h * h else h * h * x
    }
    def distance(y: A) = (x - y).abs()
    def nonNegative: Option[A] = when(n.gteq(x, n.zero))(x)
    def whenNegative(f: => A): A = nonNegative getOrElse f   //e.g. students indexOf "Greg" whenNegative Int.MaxValue
  }
  implicit class IntegralExtensions[A](val x: A)(implicit n: Integral[A]) {
    import scala.collection.immutable.NumericRange, Integral.Implicits._
    def mod(y: A): A = x - ((x / y) * y) //(x/y)*y + (x mod y) == x
    def -->(y: A): NumericRange.Inclusive[A] = NumericRange.inclusive(n.min(x, y), n.max(x, y), n.one)
  }
  implicit def toPoint[A](p: (A, A))(implicit n: Numeric[A]) = new java.awt.geom.Point2D.Double(n.toDouble(p._1), n.toDouble(p._2))
  def desc[A: Ordering]: Ordering[A] = asc[A].reverse  //e.g. students.sortBy(_.height)(desc)
  def asc[A](implicit order: Ordering[A]): Ordering[A] = order
  def map[K] = new {
    def to[V](default: V): Dict[K, V] = Dict.empty[K, V] withDefaultValue default // also to(Dict.empty[K2, V])
  }
  def memoize[A, B](f: A => B): collection.Map[A, B] = new mutable.HashMap[A, B]() {
    override def apply(key: A) = getOrElseUpdate(key, f(key))
  }
  implicit class FuzzyDouble(val x: Double) extends AnyVal {
    def  >~(y: Double) = x > y + eps
    def >=~(y: Double) = x >= y + eps
    def  ~<(y: Double) = y >=~ x
    def ~=<(y: Double) = y >~ x
    def  ~=(y: Double) = (x distance y) <= eps
  }
  @inline def when[A](check: Boolean)(f: => A): Option[A] = if (check) Some(f) else None
  def repeat[U](n: Int)(f: => U): Unit = (1 to n).foreach(_ => f)
  type of[C[_], A] = scala.collection.generic.CanBuild[A, C[A]]
  val mod: Int = (1e9 + 7).toInt
  val eps: Double = 1e-9
}
/***********************************[Scala I/O]*********************************************/
import Utils._, java.io._, java.util.StringTokenizer

class IO(in: BufferedReader, out: BufferedWriter) extends PrintWriter(out, true) with Iterator[String] {
  def this(reader: Reader, writer: Writer) = this(new BufferedReader(reader), new BufferedWriter(writer))
  def this(in: InputStream, out: OutputStream) = this(new InputStreamReader(in), new OutputStreamWriter(out))

  private[this] val tokenizers = Iterator.continually(in.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer() = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def apply[A](implicit read: IO.Read[A]): A = read.apply(this)
  def apply[C[_], A: IO.Read](n: Int)(implicit b: C of A): C[A] = Iterator.fill(n)(apply).to[C]

  def till(delim: String): String = tokenizer().get.nextToken(delim)
  def tillEndOfLine(): String = till("\n\r")

  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty

  var separator = " "
  private[this] var isNewLine = true

  def +=[A](x: A)(implicit write: IO.Write[A]): this.type = {
    write(this)(x)
    this
  }
  def ++=[A: IO.Write](xs: Traversable[A]): this.type = (this += xs.size) appendNewLine xs

  def appendNewLine[A: IO.Write](x: A): this.type = {
    println()
    this += x
  }

  override def print(obj: String) = {
    if (isNewLine) isNewLine = false else super.print(separator)
    super.print(obj)
  }
  override def println() = if (!isNewLine) {
    super.println()
    isNewLine = true
  }
  override def close() = {
    flush()
    in.close()
    super.close()
  }
}
object IO {
  class Read[A](val apply: IO => A) {
    def map[B](f: A => B): Read[B] = new Read(apply andThen f)
  }
  object Read {
    implicit def collection[C[_], A: Read](implicit b: C of A): Read[C[A]]         = new Read(r => r[C, A](r[Int]))
    implicit val string                                       : Read[String]       = new Read(_.next())
    implicit val char                                         : Read[Char]         = string.map(_.toTraversable.onlyElement)
    implicit val boolean                                      : Read[Boolean]      = string.map(_.toBoolean)
    implicit val int                                          : Read[Int]          = string.map(_.toInt)
    implicit val long                                         : Read[Long]         = string.map(_.toLong)
    implicit val bigInt                                       : Read[BigInt]       = string.map(BigInt(_))
    implicit val double                                       : Read[Double]       = string.map(_.toDouble)
    implicit val bigDecimal                                   : Read[BigDecimal]   = string.map(BigDecimal(_))
    implicit def tuple2[A: Read, B: Read]                     : Read[(A, B)]       = new Read(r => (r[A], r[B]))
    implicit def tuple3[A: Read, B: Read, C: Read]            : Read[(A, B, C)]    = new Read(r => (r[A], r[B], r[C]))
    implicit def tuple4[A: Read, B: Read, C: Read, D: Read]   : Read[(A, B, C, D)] = new Read(r => (r[A], r[B], r[C], r[D]))
  }
  trait Write[-A] {
    def apply(out: PrintWriter)(x: A): Unit
  }
  trait DefaultWrite {
    implicit def any[A]: Write[A] = Write(_.toString)
  }
  object Write extends DefaultWrite {
    def apply[A](f: A => String) = new Write[A] {
      override def apply(out: PrintWriter)(x: A) = out.print(f(x))
    }
    implicit val boolean: Write[Boolean] = Write(b => if (b) "YES" else "NO")
    implicit def tuple2[A, B]: Write[(A, B)] = Write {case (a, b) => s"$a $b"}
    implicit def array[A]: Write[Array[A]] = Write(_ mkString " ")
    implicit def iterable[A](implicit write: Write[A]): Write[Traversable[A]] = new Write[Traversable[A]] {
      override def apply(out: PrintWriter)(xs: Traversable[A]) = {
        xs foreach write(out)
        out.println()
      }
    }
  }
}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val Array(n, k) = in.next().split(' ').map(_.toInt)
  val line = in.next()
  val (at, _, _, bt, _, _) = line.indices.foldLeft((0, 0, k, 0, 0, k)) {
    case (att@(amax, acurrent, aleft, bmax, bcurrent, bleft), i) =>
//      println(att)
      val ch = line(i)
      if (ch == 'a') {
        if (bleft > 0)
          (Math.max(amax, acurrent + 1), acurrent + 1, aleft, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft - 1)
        else {
          var ni = i - bcurrent + 1
          while (ni > 0 && i - ni > 0 && line(i - ni) == 'a')
            ni -= 1
          if (ni < i  && i - ni > 0 && line(ni) == 'b')
            (Math.max(amax, acurrent + 1), acurrent + 1, aleft, Math.max(bmax, ni - 1), ni - 1, bleft)
          else
            (Math.max(amax, acurrent + 1), acurrent + 1, aleft, bmax, 0, k)
        }
      }
      else {
        if (aleft > 0)
          (Math.max(amax, acurrent + 1), acurrent + 1, aleft - 1, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft)
        else {
//          println("acurrent " + acurrent)
//          println("i = " + i)
          var ni = i - acurrent + 1
//          println("NI " + ni)
          while (ni > 0  && i - ni > 0 && line(i - ni) == 'b')
            ni -= 1
          if (ni < i && i - ni > 0 && line(i - ni) == 'a')
            (Math.max(amax, ni - 1), ni - 1, aleft, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft)
          else
            (amax, 0, k, Math.max(bmax, bcurrent + 1), bcurrent + 1, bleft)
        }
      }
  }
  println(Math.max(at, bt))
}


object E {

  import InOut._
  def main(args: Array[String]): Unit = {
    for (_ <- 1 to nextInt) {
      solve()
    }
  }

  def solve(): Unit = {
    var a = nextLong
    var b = nextLong
    var ans = 10000L

    for (test <- b to b + 10) {
      var c = a
      var times = 0L
      while (c > 0 && test != 1 && c != test) {
        c = c / test
        times += 1
      }
      if (test != 1 && c != test) ans = math.min(ans, times + test - b)
    }
    println(ans)
  }

  final object InOut {
    val in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in))
//    val in = new BufferedReader(new FileReader("./src/main/scala/input.txt"))

    val out = new java.io.PrintWriter(System.out, false)
    private[this] var tokenizer: java.util.StringTokenizer = _
    def nextToken: String = {
      while (tokenizer == null || !tokenizer.hasMoreTokens)
        tokenizer = new java.util.StringTokenizer(in.readLine)
      tokenizer.nextToken
    }
    def nextInt = Integer.parseInt(nextToken)
    def nextLong = java.lang.Long.parseLong(nextToken)
    def nextBig = BigInt(nextToken)
    def nextInts(n: Int) = Array.fill(n) { nextInt }
    def nextLongs(n: Int) = Array.fill(n) { nextLong }
    def nextBigs(n: Int) = Array.fill(n) { nextBig }
    def nextLine = in.readLine
  }
}

import java.io.BufferedReader
import java.io.ByteArrayInputStream
import java.io.InputStreamReader

object AAddandDivide {
  def solve(a: Int, b: Int): Int = {
    if (a < b) 1
    else if (a == b) {
      2
    } else {
      var min  = Int.MaxValue
      var lmin = Int.MaxValue - 1
      var i = if (b == 1) 1 else 0
      while (lmin <= min) {
        min = lmin
        var j = 1
        while (Math.pow(b + i, j) <= a) {
          j += 1
        }
        lmin = i + j
        i += 1
      }
      min
    }
  }

  def main(args: Array[String]): Unit = {
    val file = new BufferedReader(new InputStreamReader(System.in))
//        val file = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(
//          "6\n9 2\n1337 1\n1 1\n50000000 4\n991026972 997\n1234 5678".getBytes)))
//          "1\n50000000 4".getBytes)))
    val inputs = file.readLine.toInt
    var i = 0
    while (i < inputs) {
      val a::b::Nil = file.readLine.split(" ").map(_.toInt).toList
      println(solve(a, b))
      i += 1
    }
  }
}

object CP {

  import InOut._
  def main(args: Array[String]): Unit = {
    for (_ <- 1 to nextInt) {
      solve()
    }
  }

  def solve(): Unit = {
    var a = nextLong
    var b = nextLong
    var ans = 10000L

    for (test <- b to b + 10) {
      var c = a
      var times = 0L
      while (c > 0 && test != 1 && c != test) {
        c = c / test
        times += 1
      }
      if (test != 1 && c != test) ans = math.min(ans, times + test - b)
    }
    println(ans)

  }

  final object InOut {
//    import java.io.{BufferedReader, FileInputStream, FileReader, FilterInputStream, FilterReader}
//    import scala.io.Source
//    val in = new BufferedReader(new FileReader("./src/main/scala/input.txt"))
    val in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in))

    val out = new java.io.PrintWriter(System.out, false)
    private[this] var tokenizer: java.util.StringTokenizer = _
    def nextToken: String = {
      while (tokenizer == null || !tokenizer.hasMoreTokens)
        tokenizer = new java.util.StringTokenizer(in.readLine)
      tokenizer.nextToken
    }
    def nextInt = Integer.parseInt(nextToken)
    def nextLong = java.lang.Long.parseLong(nextToken)
    def nextBig = BigInt(nextToken)
    def nextInts(n: Int) = Array.fill(n) { nextInt }
    def nextLongs(n: Int) = Array.fill(n) { nextLong }
    def nextBigs(n: Int) = Array.fill(n) { nextBig }
    def nextLine = in.readLine
  }
}


object Main {
  def main(args: Array[String]): Unit = {
    val s = new Main()
    s.solve()
    s.out.flush()
  }
}

class Main {
  import java.io._
  import java.util.StringTokenizer

  import scala.collection.mutable
  import scala.util.Sorting
  import math.{abs, max, min}
  import mutable.{ArrayBuffer, ListBuffer}
  import scala.reflect.ClassTag

  val MOD = 1000000007
  val out = new PrintWriter(System.out)

  def solve(): Unit = {
    val N = ni()
    val A = na(N)
    sort(A)

    var ans = 0
    var r = 0
    REP(N) { l =>
      if (r < l) r = l
      while(r + 1 < N && A(r + 1) - A(l) <= 5) r += 1
      if (r < N && A(r) - A(l) <= 5) ans = max(ans, r - l + 1)
    }
    out.println(ans)
  }

  def sort(a: Array[Int]): Array[Int] = {
    val n = a.length
    REP(n) { i =>
      val j = scala.util.Random.nextInt(n - i) + i
      val tmp = a(i)
      a(i) = a(j)
      a(j) = tmp
    }
    Sorting.stableSort(a)
    a
  }

  private val oj = System.getenv("ATCODER_DEBUG") == null

  def DEBUG(f: => Unit): Unit = {
    if (!oj){ f }
  }

  def debug(as: Array[Boolean]): Unit = DEBUG {
    debug(as.map(x => if(x) "1" else "0").mkString)
  }

  def debug(as: Array[Int]): Unit = DEBUG {
    debug(as.mkString(" "))
  }

  def debug(as: Array[Long]): Unit = DEBUG {
    debug(as.mkString(" "))
  }

  def debug(s: => String): Unit = DEBUG {
    System.err.println(s)
  }

  def debugNum(num: => Long): Unit = DEBUG {
    System.err.println(num)
  }

  class InputReader(val stream: InputStream) {
    private val reader = new BufferedReader(new InputStreamReader(stream), 32768)
    private var tokenizer: StringTokenizer = _

    def next(): String = {
      while (tokenizer == null || !tokenizer.hasMoreTokens)
        tokenizer = new StringTokenizer(reader.readLine)
      tokenizer.nextToken
    }

    def nextInt(): Int = next().toInt
    def nextLong(): Long = next().toLong
    def nextChar(): Char = next().charAt(0)
  }
  val sc = new InputReader(System.in)
  def ni(): Int = sc.nextInt()
  def nl(): Long = sc.nextLong()
  def nc(): Char = sc.nextChar()
  def ns(): String = sc.next()
  def ns(n: Int): Array[Char] = ns().toCharArray
  def na(n: Int, offset: Int = 0): Array[Int] = map(n)(_ => ni() + offset)
  def na2(n: Int, offset: Int = 0): (Array[Int], Array[Int]) = {
    val A1, A2 = Array.ofDim[Int](n)
    REP(n) { i =>
      A1(i) = ni() + offset
      A2(i) = ni() + offset
    }
    (A1, A2)
  }
  def nm(n: Int, m: Int): Array[Array[Int]] = {
    val A = Array.ofDim[Int](n, m)
    REP(n) { i =>
      REP(m) { j =>
        A(i)(j) = ni()
      }
    }
    A
  }
  def nal(n: Int): Array[Long] = map(n)(_ => nl())
  def nm_c(n: Int, m: Int): Array[Array[Char]] = map(n) (_ => ns(m))
  def REP(n: Int, offset: Int = 0)(f: Int => Unit): Unit = {
    var i = offset
    val N = n + offset
    while(i < N) { f(i); i += 1 }
  }
  def REP_r(n: Int, offset: Int = 0)(f: Int => Unit): Unit = {
    var i = n - 1 + offset
    while(i >= offset) { f(i); i -= 1 }
  }

  def map[@specialized A: ClassTag](n: Int, offset: Int = 0)(f: Int => A): Array[A] = {
    val res = Array.ofDim[A](n)
    REP(n)(i => res(i) = f(i + offset))
    res
  }

  def sumL(as: Array[Int]): Long = {
    var s = 0L
    REP(as.length)(i => s += as(i))
    s
  }

  def cumSum(as: Array[Int]) = {
    val cum = Array.ofDim[Long](as.length + 1)
    REP(as.length) { i =>
      cum(i + 1) = cum(i) + as(i)
    }
    cum
  }
}

object C {
  import scala.collection.mutable
  def main(args: Array[String]){
    val n = readInt
    val skills = readLine().split(" ").map(_.toInt).sorted
    val max = 5
    var total = 0
    var best = 0
    var last = skills.head
    val using = mutable.SortedMap[Int, Int]()
    skills.foreach { s =>
      while(using.nonEmpty && s - using.head._1 > 5) {
      total -= using.head._2
      using -= using.head._1
    }
      total += 1
      if(!using.contains(s)) using(s) = 0
      using(s) += 1
      best = Math.max(best, total)
    }

    println(best)
  }
}

object C {
  import scala.collection.mutable
  def main(args: Array[String]){
    val n = readInt
    val skills = readLine().split(" ").map(_.toInt).sorted
    val max = 5
    var total = 0
    var best = 0
    var last = skills.head
    val using = mutable.SortedMap[Int, Int]()
    skills.foreach { s =>
      while(using.nonEmpty && s - using.head._1 > 5) {
      total -= using.head._2
      using -= using.head._1
    }
      total += 1
      if(!using.contains(s)) using(s) = 0
      using(s) += 1
    }

    println(total)
  }
}

object C {
  import scala.collection.mutable
  def main(args: Array[String]){
    val n = readInt
    val skills = readLine().split(" ").map(_.toInt).sorted
    val max = 5
    var total = 0
    var best = 0
    var last = skills.head
    val using = mutable.SortedSet[Int]()
    skills.foreach { s =>
      while(using.nonEmpty && s - using.head > 5) {
        using -= using.head
        total -= 1
      }
      total += 1
      using += s
    }

    println(total)
  }
}


import java.util.Scanner

object A extends App {
  val sc = new Scanner(System.in)

  val t = sc.nextInt

  (1 to t)
    .foreach(_ => {
      val n = sc.nextInt

      val arr = Array.tabulate(n)(_ => sc.nextLong)

      val a1 = arr.foldLeft((0L, true))((a,b) => {val t = a._1 + b; (t, a._2 && t > 0)})
      val a2 = arr.reverse.foldLeft((0L, true))((a,b) => {val t = a._1 + b; (t, a._2 && t > 0)})

      println(if (a1._2 && a2._2) "YES" else "NO")
    })

}

object Main {
    def main(args: Array[String]): Unit = {
        val t = readInt
        Iterator.fill(t)(f1).foldLeft(()){ case _ => () }
    }

    def f1(): Unit = {
        val n = readLong
        val a = readLine.split(" ").map(_.toLong)
        val (sum, l, r, list) = a.zipWithIndex.foldLeft((0L, 0L, 0L, Vector[(Long, Long, Long)]())){
            case ((sum, l, r, list), (x, i)) => {
                val newlist = if ((sum <= 0 || x <= 0) && l != r) list :+ (sum, l, r) else list
                if (sum > 0 && sum + x > 0) (sum + x, l, i + 1, newlist) else (x, i, i + 1, newlist)
            }
        }
        val x = a.sum
        if (((sum, l, r) +: list).forall{ case (s, l, r) => s < x || ( l == 0 && r == a.length) }) println("YES")
        else println("NO")
    }
}

object Main {
    def main(args: Array[String]): Unit = {
        val t = readInt
        Iterator.fill(t)(f1).foldLeft(()){ case _ => () }
    }

    def f1(): Unit = {
        val n = readInt
        val a = readLine.split(" ").map(_.toInt)
        val (sum, l, r, list) = a.zipWithIndex.foldLeft((0, 0, 0, List[(Int, Int, Int)]())){
            case ((sum, l, r, list), (x, i)) => {
                val newlist = if ((sum <= 0 || x <= 0) && l != r) list :+ (sum, l, r) else list
                if (sum > 0 && sum + x > 0) (sum + x, l, i + 1, newlist) else (x, i, i + 1, newlist)
            }
        }
        val x = a.sum
        if (((sum, l, r) +: list).forall{ case (s, l, r) => s < x || ( l == 0 && r == a.length) }) println("YES")
        else println("NO")
    }
}

object Main {
    def main(args: Array[String]): Unit = {
        val t = readInt
        Iterator.fill(t)(f1).foldLeft(()){ case _ => () }
    }

    def f1(): Unit = {
        val n = readInt
        val a = readLine.split(" ").map(_.toInt)
        val (sum, l, r, list) = a.zipWithIndex.foldLeft((0, 0, 0, List[(Int, Int, Int)]())){
            case ((sum, l, r, list), (x, i)) => {
                val newlist = if (x <= 0 && l != r) list :+ (sum, l, r) else list
                if (sum + x > 0) (sum + x, l, i + 1, newlist) else (x, i, i + 1, newlist)
            }
        }
        val x = a.sum
        if (((sum, l, r) +: list).forall{ case (s, l, r) => s < x || ( l == 0 && r == a.length) }) println("YES")
        else println("NO")
    }
}

import java.util.Scanner

object A extends App {
  val sc = new Scanner(System.in)

  val t = sc.nextInt

  (1 to t)
    .foreach(_ => {
      val n = sc.nextInt

      val arr = Array.tabulate(n)(_ => sc.nextInt)

      val a1 = arr.foldLeft((0, true))((a,b) => {val t = a._1 + b; (t, a._2 && t > 0)})
      val a2 = arr.reverse.foldLeft((0, true))((a,b) => {val t = a._1 + b; (t, a._2 && t > 0)})

      println(if (a1._2 && a2._2) "YES" else "NO")
    })

}


object Solution extends App {
  val in = io.Source.stdin.getLines()
  val line = in.next().split("@", -1)
  if (line.contains("") || line.length < 2 || line.drop(1).dropRight(1).exists(_.length == 1))
    println("No solution")
  else
    println(line.indices.flatMap{
      case (0) => List(line(0))
      case (i) if i == line.length - 1 => List(line(line.length - 1))
      case (i) => List(line(i).head, line(i).tail)
    }.grouped(2).map(_.mkString("@")).mkString(","))
}

import scala.io._
import scala.collection.mutable._
import java.util.StringTokenizer

object HelloWorld {

  def main(args: Array[String]): Unit = {
    var s = readLine;
    if (s.startsWith("@") || s.endsWith("@") || !s.contains("@")) {
      println("No solution");
      return;
    }
    var ss = s.split("@");
    var atCount = s.count(_.toChar == '@')
    if (ss.length - 1 != atCount) {
      println("No solution");
      return;
    }
    for (i <- 0 until ss.length) {
      if (i != 0 && i != ss.length - 1) {
        if (ss(i).length <= 1) {
          println("No solution");
          return;
        }
      }
    }
    var result = "";
    var prev = false;
    var atNumber = 0;
    for (e <- s) {
      result += e;
      if (prev && atNumber != atCount) {
        result += ",";
        prev = false;
      }
      if (e == '@') {
        atNumber += 1;
        prev = true;
      }
    }
    println(result);
  }

}

object Solution extends App {
  val in = io.Source.stdin.getLines()
  val line = in.next().split("@", -1)
  if (line.contains("") || line.drop(1).dropRight(1).exists(_.length == 1))
    println("No solution")
  else
    println(line.indices.flatMap{
      case (0) => List(line(0))
      case (i) if i == line.length - 1 => List(line(line.length - 1))
      case (i) => List(line(i).head, line(i).tail)
    }.grouped(2).map(_.mkString("@")).mkString(","))
}

import scala.io._
import scala.collection.mutable._
import java.util.StringTokenizer

object HelloWorld {

  def main(args: Array[String]): Unit = {
    var s = readLine;
    if (s.startsWith("@") || s.endsWith("@")) {
      println("No solution");
      return;
    }
    var ss = s.split("@");
    var atCount = s.count(_.toChar == '@')
    if (ss.length - 1 != atCount) {
      println("No solution");
      return;
    }
    for (i <- 0 until ss.length) {
      if (i != 0 && i != ss.length - 1) {
        if (ss(i).length <= 1) {
          println("No solution");
          return;
        }
      }
    }
    var result = "";
    var prev = false;
    var atNumber = 0;
    for (e <- s) {
      result += e;
      if (prev && atNumber != atCount) {
        result += ",";
        prev = false;
      }
      if (e == '@') {
        atNumber += 1;
        prev = true;
      }
    }
    println(result);
  }

}


import java.util.Scanner
import scala.collection.JavaConverters._

object Main extends App {
  val sc = new java.util.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vsp = Array.tabulate(n+1)(_ => (new java.util.HashSet[Int]()).asScala)

  es foreach { e =>
    vsp(e._1) += e._2
    vsp(e._2) += e._1
  }

  val vs = vsp

  def makeHydra(vh: Int, vt: Int): Boolean = {
    if (vs(vh).size > h && vs(vt).size > t && (vs(vh) ++ vs(vt)).size >= h + t + 2) {
      println("YES")
      println("%d %d".format(vh, vt))
      val cm = (vs(vh) & vs(vt)).toSeq
      val rh = (vs(vh) - vt -- cm).toSeq ++ cm ++ (vs(vt) - vh -- cm).toSeq
      println(rh.take(h).mkString(" "))
      println(rh.takeRight(t).mkString(" "))

      true
    } else false
  }

  es sortBy { case (src, dst) =>
    - (vs(src).size + vs(dst).size)
  } indexWhere { e =>
    makeHydra(e._1, e._2) || makeHydra(e._2, e._1)
  } match {
    case -1 => println("NO");
    case _ => Unit
  }
}

import java.util.Scanner
import scala.collection.mutable.ListBuffer

object Main extends App {
  val sc = new java.util.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vsp = Array.tabulate(n+1)(_ => ListBuffer[Int]())

  es foreach { e =>
    vsp(e._1) += e._2
    vsp(e._2) += e._1
  }

  val vs = vsp.map(_.toSet)

  def makeHydra(vh: Int, vt: Int): Boolean = {
    if (vs(vh).size > h && vs(vt).size > t && (vs(vh) ++ vs(vt)).size >= h + t + 2) {
      println("YES")
      println("%d %d".format(vh, vt))
      val cm = (vs(vh) & vs(vt)).toSeq
      val rh = (vs(vh) - vt -- cm).toSeq ++ cm ++ (vs(vt) - vh -- cm).toSeq
      println(rh.take(h).mkString(" "))
      println(rh.takeRight(t).mkString(" "))

      true
    } else false
  }

  es sortBy { case (src, dst) =>
    - (vs(src).size + vs(dst).size)
  } indexWhere { e =>
    makeHydra(e._1, e._2) || makeHydra(e._2, e._1)
  } match {
    case -1 => println("NO");
    case _ => Unit
  }
}

object Main extends App {
  import java.{util => ju}
  import scala.collection.JavaConverters._

  val sc = new ju.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vsp = Array.tabulate(n+1)(_ => (new ju.HashSet[Int]()).asScala)

  es foreach { case (src, dst) =>
    vsp(src) += dst
    vsp(dst) += src
  }

  val vs = vsp

  def makeHydra(vh: Int, vt: Int): Boolean = {
    if (vs(vh).size > h && vs(vt).size > t && (vs(vh) ++ vs(vt)).size >= h + t + 2) {
      println("YES")
      println("%d %d".format(vh, vt))
      val cm = (vs(vh) & vs(vt)).toSeq
      val rh = (vs(vh) - vt -- cm).toSeq ++ cm ++ (vs(vt) - vh -- cm).toSeq
      println(rh.take(h).mkString(" "))
      println(rh.takeRight(t).mkString(" "))

      true
    } else false
  }

  es sortBy { case (src, dst) =>
    - (vs(src).size + vs(dst).size)
  } indexWhere { case (src, dst) =>
    makeHydra(src, dst) || makeHydra(dst, src)
  } match {
    case -1 => println("NO");
    case _ => Unit
  }
}

import java.util.Scanner
import scala.collection.mutable.ListBuffer

object Main extends App {
  val sc = new java.util.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vsp = Array.tabulate(n+1)(_ => ListBuffer[Int]())

  es foreach { e =>
    vsp(e._1) += e._2
    vsp(e._2) += e._1
  }

  val vs = vsp.map(_.toSet)

  def makeHydra(vh: Int, vt: Int): Boolean = {
    if (vs(vh).size > h && vs(vt).size > t && (vs(vh) ++ vs(vt)).size >= h + t + 2) {
      println("YES")
      println("%d %d".format(vh, vt))
      val cm = (vs(vh) & vs(vt)).toSeq
      val rh = (vs(vh) - vt -- cm).toSeq ++ cm
      val rt = cm.reverse ++ (vs(vt) - vh -- cm).toSeq
      println(rh.take(h).mkString(" "))
      println(rt.takeRight(t).mkString(" "))

      true
    } else false
  }

  es indexWhere { e =>
    makeHydra(e._1, e._2) || makeHydra(e._2, e._1)
  } match {
    case -1 => println("NO");
    case _ => Unit
  }
}

import java.util.Scanner
import scala.collection.mutable._

object Main extends App {
  val sc = new java.util.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vs = Array.tabulate(n+1)(_ => Set[Int]())

  es foreach { e =>
    vs(e._1) += e._2
    vs(e._2) += e._1
  }

  def makeHydra(vh: Int, vt: Int): Boolean = {
    val cm = vs(vh) & vs(vt)
    if (vs(vh).size > h && vs(vt).size > t && vs(vh).size + vs(vt).size + cm.size >=  h + t + 2) {
      println("YES")
      println("%d %d".format(vh, vt))

      val rv = (vs(vh) - vt -- cm).toList ++ cm.toList ++ (vs(vt) - vh -- cm).toList

      println(rv.take(h).mkString(" "))
      println(rv.takeRight(t).mkString(" "))

      true
    } else false
  }

  es indexWhere { e =>
    makeHydra(e._1, e._2) || makeHydra(e._2, e._1)
  } match {
    case -1 => println("NO");
    case _ => Unit
  }
}

import java.util.Scanner
import scala.collection.mutable._

object Main extends App {
  val sc = new java.util.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vs = Array.tabulate(n+1)(_ => Set[Int]())

  es foreach { e =>
    vs(e._1) += e._2
    vs(e._2) += e._1
  }

  def makeHydra(vh: Int, vt: Int): Boolean = {
    if (vs(vh).size > h && vs(vt).size > t && (vs(vh) ++ vs(vt)).size >= h + t + 2) {
      println("%d %d".format(vh, vt))

      val cm = vs(vh) & vs(vt)
      val rv = (vs(vh) - vt -- cm).toList ++ cm.toList ++ (vs(vt) - vh -- cm).toList

      println(rv.take(h).mkString(" "))
      println(rv.takeRight(t).mkString(" "))

      true
    } else false
  }

  es indexWhere { e =>
    makeHydra(e._1, e._2) || makeHydra(e._2, e._1)
  }
}

import java.util.Scanner
import scala.collection.mutable.ListBuffer

object Main extends App {
  val sc = new java.util.Scanner(System.in)

  val n, m, h, t = sc.nextInt

  val es = Array.tabulate(m)(_ => (sc.nextInt(), sc.nextInt()))

  val vsp = Array.tabulate(n+1)(_ => ListBuffer[Int]())

  es foreach { e =>
    vsp(e._1) += e._2
    vsp(e._2) += e._1
  }

  val vs = vsp.map(_.toSet)

  def makeHydra(vh: Int, vt: Int): Boolean = {
    if (vs(vh).size > h && vs(vt).size > t && (vs(vh) ++ vs(vt)).size >= h + t + 2) {
      println("YES")
      println("%d %d".format(vh, vt))
      return true

      val cm = (vs(vh) & vs(vt)).toArray
      val rh = (vs(vh) - vt -- cm)
      val rt = (vs(vt) - vh -- cm).take(t).toArray ++ cm.reverse.take(t)

      println(rh.take(h).mkString(" "))
      println(rt.take(t).mkString(" "))

      true
    } else false
  }

  es indexWhere { e =>
    makeHydra(e._1, e._2) || makeHydra(e._2, e._1)
  } match {
    case -1 => println("NO");
    case _ => Unit
  }
}