https://coderun.yandex.ru/problem/magic-substring Сложная

Решение

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter

// Функция для проверки, является ли окно "магическим" по отношению к строке S
// Принимает массивы частот символов для окна (windowCounts) и строки S (sCounts)
fun isMagical(windowCounts: IntArray, sCounts: IntArray): Boolean {
    var diffs = 0 // Счетчик различий в частотах символов
    var extraWindowChar = -1 // Индекс символа, которого больше в окне
    var extraSChar = -1 // Индекс символа, которого больше в строке S

    // Проходим по всем возможным символам (a-z)
    for (i in 0 until 26) {
        // Если частоты символа различаются
        if (windowCounts[i] != sCounts[i]) {
            // Если в окне на 1 символ больше
            if (windowCounts[i] == sCounts[i] + 1) {
                // Если уже найден другой лишний символ в окне, то не магическая
                if (extraWindowChar != -1) return false
                extraWindowChar = i // Запоминаем индекс лишнего символа в окне
                diffs++ // Увеличиваем счетчик различий
            }
            // Если в строке S на 1 символ больше
            else if (sCounts[i] == windowCounts[i] + 1) {
                // Если уже найден другой лишний символ в S, то не магическая
                if (extraSChar != -1) return false
                extraSChar = i // Запоминаем индекс лишнего символа в S
                diffs++ // Увеличиваем счетчик различий
            }
            // Если разница в частотах не равна 1, то не магическая
            else {
                return false
            }
        }
    }
    // Магическая, если ровно два различия (по одному в каждую сторону)
    return diffs == 2
}

fun main(args: Array<String>) {
    // Используем BufferedReader для быстрого чтения
    val reader = BufferedReader(InputStreamReader(System.`in`))
    // Используем BufferedWriter для быстрого вывода
    val writer = BufferedWriter(OutputStreamWriter(System.out))

    // Читаем текст T и строку S
    val t = reader.readLine()
    val s = reader.readLine()
    val n = t.length // Длина текста T
    val m = s.length // Длина строки S

    // Обработка крайних случаев: если S пустая или длиннее T, магической подстроки нет
    if (m == 0 || n < m) {
        writer.write("-1")
        writer.newLine()
        writer.flush() // Сбрасываем буфер вывода
        return
    }

    // Массивы для хранения частот символов (26 букв английского алфавита)
    val sCounts = IntArray(26) // Частоты для строки S
    val windowCounts = IntArray(26) // Частоты для текущего окна в T

    // Считаем частоты символов в строке S
    for (char in s) {
        sCounts[char - 'a']++
    }

    // Считаем частоты символов для первого окна в T (длиной m)
    for (i in 0 until m) {
        windowCounts[t[i] - 'a']++
    }

    // Проверяем, является ли первое окно магическим
    if (isMagical(windowCounts, sCounts)) {
        writer.write("0") // Если да, выводим индекс 0
        writer.newLine()
        writer.flush()
        return
    }

    // Используем метод скользящего окна
    // Проходим по тексту T, сдвигая окно на 1 символ вправо на каждой итерации
    for (i in m until n) {
        // Убираем символ, который выходит из окна слева
        windowCounts[t[i - m] - 'a']--
        // Добавляем символ, который входит в окно справа
        windowCounts[t[i] - 'a']++

        // Проверяем, является ли текущее окно магическим
        if (isMagical(windowCounts, sCounts)) {
            // Если да, выводим начальный индекс этого окна (i - m + 1)
            writer.write((i - m + 1).toString())
            writer.newLine()
            writer.flush()
            return // Нашли первое вхождение, завершаем работу
        }
    }

    // Если прошли весь текст и не нашли магической подстроки
    writer.write("-1")
    writer.newLine()
    writer.flush() // Не забываем сбросить буфер
}