Декодировать строку, которая содержит закодированный шаблон - PullRequest
0 голосов
/ 09 апреля 2019

Рассмотрим следующую проблему:

string s = "fffffssss" 

Кодированная строка будет 5xf4xs, но что, если в s есть закодированный шаблон? Например, s="5xfxxx", что мне делать в кодировщике, чтобы избежать неоднозначности? при условии, что закодированная строка должна быть короче исходной.

Ответы [ 3 ]

0 голосов
/ 09 апреля 2019

Если вы хотите сохранить ту же схему кодирования, где dxc приводит к d (цифре) повторений c (символ), тогда вы можете просто кодировать входные данные например, 5xy с 51xxy. Да, вы будете платить цену в 2 дополнительных символа всякий раз, когда найдете цифру, за которой следует x на входе.

Нет кодирования (без потерь), которое гарантирует, что выходной сигнал всегда будет короче входного. Еще сильнее: не существует кодировки, которая гарантировала бы, что он всегда будет создавать выходные данные либо длины ввода, либо короче, за исключением того, что вообще ничего не кодирует (что всегда будет давать длину вывода, равную его входу). Все схемы сжатия основаны на избыточности входных данных и вообще ничего не сжимают с действительно случайными данными. Поэтому, хороша или нет схема сжатия, зависит от того, сможет ли она эффективно использовать избыточность в ожидаемых входных данных.

Простая схема, гарантирующая, что вы никогда не заплатите штраф в размере более 1 символа, - это использование начального токена, чтобы указать, закодирована строка или нет. Например, скажите, что 1-ый символ - 0, если кодирование не было выполнено, и 1, если он закодирован. Тогда

encode("1x2x3x4x") = "01x2x3x4x"; // only 1 character longer than input
encode("1x2x3x4x") = "111xx21xx31xx41xx"; // not so good: 8 chars longer
0 голосов
/ 09 апреля 2019

Я предполагаю, что «aaaaaaaaaa» будет закодирован как «10xa», что означает, что «множитель» n в произведенном паттерне nxc может состоять из более чем одной цифры.

Одна из идей состоит в том, чтобы ввести специальный escape-символ, такой как, например, хеш "#". Всякий раз, когда вход имеет последовательность цифр, пусть алгоритм кодирования добавляет хеш после такой последовательности. Таким образом, его нельзя спутать с шаблоном nxc . В декодировании вы удалили бы такой конечный хеш.

Всякий раз, когда у входа есть хеш, затем экранируйте его так же, как указано выше: добавьте дополнительный хеш сразу после него.

Итак, в вашем примере, 5xfxxx будет закодировано как 5#xf3xx. Однако, если последовательность цифр может быть записана в нотации nxc , то хеш не будет использоваться. Поэтому 999x1 будет закодировано как 3x91, а 122x1 будет закодировано как 122#x1. Точно так же, ### будет закодирован как 3x#, без экранирования любого хэша. Поэтому применение шаблона nxc всегда будет иметь приоритет над экранированием.

Вот небольшая реализация JavaScript этих функций кодирования / декодирования, в значительной степени опирающаяся на замены на основе регулярных выражений . Вы можете играть с ним:

function encode(s) {
    // If a character occurs 3 or more times in sequence, encode that sequence;
    // Otherwise, append a hash after any sequence of digits, 
    //            and after each individual hash:
    return s.replace(/(.)\1\1+|\d+|#/g, (m, ch) => 
        ch ? m.length + "x" + ch : m + "#");
}

function decode(s) {
    // If a nxc sequence is found, decode it
    // Otherwise, if a character is followed by a hash, remove the hash
    return s.replace(/(\d+)x(.)|(.)#/g, (m, times, ch, esc) => 
        times ? ch.repeat(+times) : esc);
}

// I/O management of this snippet:
let elemInput = document.querySelector("#input");
let elemEncoded = document.querySelector("#encoded");
let elemDecoded = document.querySelector("#decoded");
let elemCheck = document.querySelector("#check");
elemInput.addEventListener("input", function () { // Whenever input changes:
    let encoded = encode(this.value); // Encode...
    let decoded = decode(encoded); // ...and decode the encoded string again
    elemEncoded.textContent = encoded;
    elemDecoded.textContent = decoded;
    // Check whether the decoded string is equal to the input:
    elemCheck.textContent = this.value == decoded ? "OK" : "Difference!";
});
Input: <input id="input">
<div>Encoded: <span id="encoded"></span></div>
<div>Decoded: <span id="decoded"></span></div>
<div>Check: <span id="check"></span></div>

Очевидно, это означает, что некоторые входы будут иметь закодированный эквивалент, который длиннее исходного ввода. Если вы не используете алгоритм, который всегда кодирует строку, которая равна длине ввода, или если выход не может содержать что-то, что никогда не может появиться на входе, невозможно предотвратить случаи, когда выходной файл длиннее входного. .

Примечание: я удалил флаг s из регулярных выражений, так как не все браузеры его поддерживают, но он должен быть там, если в вашем вводе могут появляться новые строки.

0 голосов
/ 09 апреля 2019

Для кодирования 5xfxxx вы получите 1x51xx1xf3xx, который не имеет никакой двусмысленности (есть только один способ декодировать такую ​​строку, вы должны рассмотреть триплеты). Все может стать немного сложнее, если в вашей строке более 10 одинаковых символов, но двусмысленности не будет.

Что касается ограничения на то, что закодированная строка должна быть короче исходной, такой гарантии нет. x будет закодировано как 1xx, что в три раза дольше. Это ваш худший сценарий: результат в 3 раза длиннее исходного.

Если вы ищете способы сжатия строки, я предлагаю вам взглянуть на кодирование Хаффмана , которое является простым и эффективным (оно почти оптимально в отношении сжатия и работает за линейное время ). Вы должны будете рассмотреть двоичные строки, хотя.

...