<?php

error_reporting(-1);
mb_internal_encoding('utf-8');

function getLetterCounts($word)
{
    return array(
        'cyr' => preg_match_all('/[а-яё]/ui', $word),
        'lat' => preg_match_all('/[a-z]/i', $word)
    );
}

$latToCyr = array(
    'a' => 'а', 'c' => 'с', 'e' => 'е', 'o' => 'о', 'p' => 'р', 'x' => 'х',
    'y' => 'у', 'k' => 'к', 'm' => 'м', 't' => 'т', 'h' => 'н', 'b' => 'в',
    'A' => 'А', 'B' => 'В', 'C' => 'С', 'E' => 'Е', 'H' => 'Н', 'K' => 'К',
    'M' => 'М', 'O' => 'О', 'P' => 'Р', 'T' => 'Т', 'X' => 'Х', 'Y' => 'У'
);
$cyrToLat = array_flip($latToCyr);

$text = <<<EOF
Администрация объявляет конкурс на поставку кaнцелярских тoваров
на сумму 100500 руб.
EOF;

$matches = array();
preg_match_all('/[а-яёa-z]+/ui', $text, $matches);

foreach ($matches[0] as $word) {
    $counts = getLetterCounts($word);

    if ($counts['cyr'] == 0 || $counts['lat'] == 0) {
        continue;
    }

    if ($counts['cyr'] >= $counts['lat']) {
        $marked = preg_replace('/[a-z]/i', '[$0]', $word, 1);
    } else {
        $marked = preg_replace('/[а-яё]/ui', '[$0]', $word, 1);
    }

    echo "Опечатка в слове {$word}: {$marked}\n";
}

$fixedText = preg_replace_callback('/[а-яёa-z]+/ui', function ($match) use ($latToCyr, $cyrToLat) {
    $word = $match[0];
    $counts = getLetterCounts($word);

    if ($counts['cyr'] == 0 || $counts['lat'] == 0) {
        return $word;
    }

    if ($counts['cyr'] >= $counts['lat']) {
        return strtr($word, $latToCyr);
    }

    return strtr($word, $cyrToLat);
}, $text);

echo "Исправленный текст:\n{$fixedText}\n";