From 6b69060c8ebe0a8d7193705f151366d52a8dd063 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Thu, 27 Mar 2025 08:52:52 +0200 Subject: [PATCH] Improved task 2213 --- .../Solution.kt | 122 ++++++++---------- 1 file changed, 52 insertions(+), 70 deletions(-) diff --git a/src/main/kotlin/g2201_2300/s2213_longest_substring_of_one_repeating_character/Solution.kt b/src/main/kotlin/g2201_2300/s2213_longest_substring_of_one_repeating_character/Solution.kt index 280a79894..9e132f69a 100644 --- a/src/main/kotlin/g2201_2300/s2213_longest_substring_of_one_repeating_character/Solution.kt +++ b/src/main/kotlin/g2201_2300/s2213_longest_substring_of_one_repeating_character/Solution.kt @@ -1,89 +1,71 @@ package g2201_2300.s2213_longest_substring_of_one_repeating_character // #Hard #Array #String #Ordered_Set #Segment_Tree -// #2023_06_27_Time_879_ms_(100.00%)_Space_64.8_MB_(100.00%) +// #2025_03_27_Time_73_ms_(100.00%)_Space_73.52_MB_(100.00%) class Solution { - internal class TreeNode(var start: Int, var end: Int) { - var leftChar = 0.toChar() - var leftCharLen = 0 - var rightChar = 0.toChar() - var rightCharLen = 0 - var max = 0 - var left: TreeNode? = null - var right: TreeNode? = null - } + private lateinit var ca: CharArray fun longestRepeating(s: String, queryCharacters: String, queryIndices: IntArray): IntArray { - val sChar = s.toCharArray() - val qChar = queryCharacters.toCharArray() - val root = buildTree(sChar, 0, sChar.size - 1) - val result = IntArray(qChar.size) - for (i in qChar.indices) { - updateTree(root, queryIndices[i], qChar[i]) - if (root != null) { - result[i] = root.max - } + ca = s.toCharArray() + val result = IntArray(queryIndices.size) + val root = SegmentTree(0, ca.size) + for (i in queryIndices.indices) { + ca[queryIndices[i]] = queryCharacters[i] + root.update(queryIndices[i]) + result[i] = root.longest } return result } - private fun buildTree(s: CharArray, from: Int, to: Int): TreeNode? { - if (from > to) { - return null - } - val root = TreeNode(from, to) - if (from == to) { - root.max = 1 - root.leftChar = s[from] - root.rightChar = root.leftChar - root.rightCharLen = 1 - root.leftCharLen = root.rightCharLen - return root - } - val middle = from + (to - from) / 2 - root.left = buildTree(s, from, middle) - root.right = buildTree(s, middle + 1, to) - updateNode(root) - return root - } + private inner class SegmentTree(val start: Int, val end: Int) { + var longest: Int = 0 + var leftLength: Int = 0 + var rightLength: Int = 0 + private lateinit var left: SegmentTree + private lateinit var right: SegmentTree - private fun updateTree(root: TreeNode?, index: Int, c: Char) { - if (root == null || root.start > index || root.end < index) { - return - } - if (root.start == index && root.end == index) { - root.rightChar = c - root.leftChar = root.rightChar - return + init { + if (end - start > 1) { + val mid = (start + end) / 2 + left = SegmentTree(start, mid) + right = SegmentTree(mid, end) + merge() + } else { + longest = 1 + leftLength = 1 + rightLength = 1 + } } - updateTree(root.left, index, c) - updateTree(root.right, index, c) - updateNode(root) - } - private fun updateNode(root: TreeNode?) { - if (root == null) { - return - } - root.leftChar = root.left!!.leftChar - root.leftCharLen = root.left!!.leftCharLen - root.rightChar = root.right!!.rightChar - root.rightCharLen = root.right!!.rightCharLen - root.max = Math.max(root.left!!.max, root.right!!.max) - if (root.left!!.rightChar == root.right!!.leftChar) { - val len = root.left!!.rightCharLen + root.right!!.leftCharLen - if (root.left!!.leftChar == root.left!!.rightChar && - root.left!!.leftCharLen == root.left!!.end - root.left!!.start + 1 - ) { - root.leftCharLen = len + fun update(index: Int) { + if (end - start == 1) return + if (index < (left.end)) { + left.update(index) + } else { + right.update(index) } - if (root.right!!.leftChar == root.right!!.rightChar && - root.right!!.leftCharLen == root.right!!.end - root.right!!.start + 1 - ) { - root.rightCharLen = len + merge() + } + + private fun merge() { + longest = maxOf(left.longest, right.longest) + if (ca[left.end - 1] == ca[right.start]) { + longest = maxOf(longest, left.rightLength + right.leftLength) + leftLength = if (left.leftLength == left.end - left.start) { + left.leftLength + right.leftLength + } else { + left.leftLength + } + rightLength = if (right.rightLength == (right.end - right.start)) { + right.rightLength + left.rightLength + } else { + right.rightLength + } + } else { + leftLength = left.leftLength + rightLength = right.rightLength } - root.max = Math.max(root.max, len) } } }