|  | 
| 1 | 1 | package g2201_2300.s2213_longest_substring_of_one_repeating_character | 
| 2 | 2 | 
 | 
| 3 | 3 | // #Hard #Array #String #Ordered_Set #Segment_Tree | 
| 4 |  | -// #2023_06_27_Time_879_ms_(100.00%)_Space_64.8_MB_(100.00%) | 
|  | 4 | +// #2025_03_27_Time_73_ms_(100.00%)_Space_73.52_MB_(100.00%) | 
| 5 | 5 | 
 | 
| 6 | 6 | class Solution { | 
| 7 |  | -    internal class TreeNode(var start: Int, var end: Int) { | 
| 8 |  | -        var leftChar = 0.toChar() | 
| 9 |  | -        var leftCharLen = 0 | 
| 10 |  | -        var rightChar = 0.toChar() | 
| 11 |  | -        var rightCharLen = 0 | 
| 12 |  | -        var max = 0 | 
| 13 |  | -        var left: TreeNode? = null | 
| 14 |  | -        var right: TreeNode? = null | 
| 15 |  | -    } | 
|  | 7 | +    private lateinit var ca: CharArray | 
| 16 | 8 | 
 | 
| 17 | 9 |     fun longestRepeating(s: String, queryCharacters: String, queryIndices: IntArray): IntArray { | 
| 18 |  | -        val sChar = s.toCharArray() | 
| 19 |  | -        val qChar = queryCharacters.toCharArray() | 
| 20 |  | -        val root = buildTree(sChar, 0, sChar.size - 1) | 
| 21 |  | -        val result = IntArray(qChar.size) | 
| 22 |  | -        for (i in qChar.indices) { | 
| 23 |  | -            updateTree(root, queryIndices[i], qChar[i]) | 
| 24 |  | -            if (root != null) { | 
| 25 |  | -                result[i] = root.max | 
| 26 |  | -            } | 
|  | 10 | +        ca = s.toCharArray() | 
|  | 11 | +        val result = IntArray(queryIndices.size) | 
|  | 12 | +        val root = SegmentTree(0, ca.size) | 
|  | 13 | +        for (i in queryIndices.indices) { | 
|  | 14 | +            ca[queryIndices[i]] = queryCharacters[i] | 
|  | 15 | +            root.update(queryIndices[i]) | 
|  | 16 | +            result[i] = root.longest | 
| 27 | 17 |         } | 
| 28 | 18 |         return result | 
| 29 | 19 |     } | 
| 30 | 20 | 
 | 
| 31 |  | -    private fun buildTree(s: CharArray, from: Int, to: Int): TreeNode? { | 
| 32 |  | -        if (from > to) { | 
| 33 |  | -            return null | 
| 34 |  | -        } | 
| 35 |  | -        val root = TreeNode(from, to) | 
| 36 |  | -        if (from == to) { | 
| 37 |  | -            root.max = 1 | 
| 38 |  | -            root.leftChar = s[from] | 
| 39 |  | -            root.rightChar = root.leftChar | 
| 40 |  | -            root.rightCharLen = 1 | 
| 41 |  | -            root.leftCharLen = root.rightCharLen | 
| 42 |  | -            return root | 
| 43 |  | -        } | 
| 44 |  | -        val middle = from + (to - from) / 2 | 
| 45 |  | -        root.left = buildTree(s, from, middle) | 
| 46 |  | -        root.right = buildTree(s, middle + 1, to) | 
| 47 |  | -        updateNode(root) | 
| 48 |  | -        return root | 
| 49 |  | -    } | 
|  | 21 | +    private inner class SegmentTree(val start: Int, val end: Int) { | 
|  | 22 | +        var longest: Int = 0 | 
|  | 23 | +        var leftLength: Int = 0 | 
|  | 24 | +        var rightLength: Int = 0 | 
|  | 25 | +        private lateinit var left: SegmentTree | 
|  | 26 | +        private lateinit var right: SegmentTree | 
| 50 | 27 | 
 | 
| 51 |  | -    private fun updateTree(root: TreeNode?, index: Int, c: Char) { | 
| 52 |  | -        if (root == null || root.start > index || root.end < index) { | 
| 53 |  | -            return | 
| 54 |  | -        } | 
| 55 |  | -        if (root.start == index && root.end == index) { | 
| 56 |  | -            root.rightChar = c | 
| 57 |  | -            root.leftChar = root.rightChar | 
| 58 |  | -            return | 
|  | 28 | +        init { | 
|  | 29 | +            if (end - start > 1) { | 
|  | 30 | +                val mid = (start + end) / 2 | 
|  | 31 | +                left = SegmentTree(start, mid) | 
|  | 32 | +                right = SegmentTree(mid, end) | 
|  | 33 | +                merge() | 
|  | 34 | +            } else { | 
|  | 35 | +                longest = 1 | 
|  | 36 | +                leftLength = 1 | 
|  | 37 | +                rightLength = 1 | 
|  | 38 | +            } | 
| 59 | 39 |         } | 
| 60 |  | -        updateTree(root.left, index, c) | 
| 61 |  | -        updateTree(root.right, index, c) | 
| 62 |  | -        updateNode(root) | 
| 63 |  | -    } | 
| 64 | 40 | 
 | 
| 65 |  | -    private fun updateNode(root: TreeNode?) { | 
| 66 |  | -        if (root == null) { | 
| 67 |  | -            return | 
| 68 |  | -        } | 
| 69 |  | -        root.leftChar = root.left!!.leftChar | 
| 70 |  | -        root.leftCharLen = root.left!!.leftCharLen | 
| 71 |  | -        root.rightChar = root.right!!.rightChar | 
| 72 |  | -        root.rightCharLen = root.right!!.rightCharLen | 
| 73 |  | -        root.max = Math.max(root.left!!.max, root.right!!.max) | 
| 74 |  | -        if (root.left!!.rightChar == root.right!!.leftChar) { | 
| 75 |  | -            val len = root.left!!.rightCharLen + root.right!!.leftCharLen | 
| 76 |  | -            if (root.left!!.leftChar == root.left!!.rightChar && | 
| 77 |  | -                root.left!!.leftCharLen == root.left!!.end - root.left!!.start + 1 | 
| 78 |  | -            ) { | 
| 79 |  | -                root.leftCharLen = len | 
|  | 41 | +        fun update(index: Int) { | 
|  | 42 | +            if (end - start == 1) return | 
|  | 43 | +            if (index < (left.end)) { | 
|  | 44 | +                left.update(index) | 
|  | 45 | +            } else { | 
|  | 46 | +                right.update(index) | 
| 80 | 47 |             } | 
| 81 |  | -            if (root.right!!.leftChar == root.right!!.rightChar && | 
| 82 |  | -                root.right!!.leftCharLen == root.right!!.end - root.right!!.start + 1 | 
| 83 |  | -            ) { | 
| 84 |  | -                root.rightCharLen = len | 
|  | 48 | +            merge() | 
|  | 49 | +        } | 
|  | 50 | + | 
|  | 51 | +        private fun merge() { | 
|  | 52 | +            longest = maxOf(left.longest, right.longest) | 
|  | 53 | +            if (ca[left.end - 1] == ca[right.start]) { | 
|  | 54 | +                longest = maxOf(longest, left.rightLength + right.leftLength) | 
|  | 55 | +                leftLength = if (left.leftLength == left.end - left.start) { | 
|  | 56 | +                    left.leftLength + right.leftLength | 
|  | 57 | +                } else { | 
|  | 58 | +                    left.leftLength | 
|  | 59 | +                } | 
|  | 60 | +                rightLength = if (right.rightLength == (right.end - right.start)) { | 
|  | 61 | +                    right.rightLength + left.rightLength | 
|  | 62 | +                } else { | 
|  | 63 | +                    right.rightLength | 
|  | 64 | +                } | 
|  | 65 | +            } else { | 
|  | 66 | +                leftLength = left.leftLength | 
|  | 67 | +                rightLength = right.rightLength | 
| 85 | 68 |             } | 
| 86 |  | -            root.max = Math.max(root.max, len) | 
| 87 | 69 |         } | 
| 88 | 70 |     } | 
| 89 | 71 | } | 
0 commit comments