Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth
Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Boost your online presence with premium web hosting and servers

Disclosure: My content contains affiliate links.

42,844 questions

55,671 answers

573 users

How to perform high‑performance reversible text compression using a word dictionary in PHP

1 Answer

0 votes
/*
    =====================================================================
    High‑Performance Reversible Text Compression Using a Word Dictionary
    ---------------------------------------------------------------------
    This program compresses text by replacing repeated words with tokens
    like @0, @1, @2... and stores each unique word in a dictionary.

    The compressed text is fully reversible.

    WHY THIS VERSION IS FAST (PHP):
    -------------------------------
    • Uses associative arrays for O(1) average lookup.
    • Uses indexed arrays for compact dictionary storage.
    • Uses manual scanning instead of regex (much faster).
    • Clean, idiomatic, modern PHP design.

    OUTPUT EXAMPLE:
        Original:      this is is a test test compression string string test
        Compressed:    @0 @1 @1 @2 @3 @3 @4 @5 @5 @3
        Decompressed:  this is is a test test compression string string test
    =====================================================================
*/


// ---------------------------------------------------------------------
// Dictionary structure: indexed array + associative array
// ---------------------------------------------------------------------
class WordDictionary {
    public array $words = [];      // index → word
    public array $indexMap = [];   // word → index
}


// ---------------------------------------------------------------------
// Find or add a word to the dictionary (O(1) average)
// ---------------------------------------------------------------------
function findOrAdd(WordDictionary $dict, string $word): int {
    if (isset($dict->indexMap[$word])) {
        return $dict->indexMap[$word];
    }

    $newIndex = count($dict->words);
    $dict->words[] = $word;
    $dict->indexMap[$word] = $newIndex;

    return $newIndex;
}


// ---------------------------------------------------------------------
// Compress text into @ID tokens
// ---------------------------------------------------------------------
function compress(string $input, WordDictionary $dict): string {
    $out = '';
    $len = strlen($input);
    $i = 0;

    while ($i < $len) {

        $c = $input[$i];

        // Pass punctuation/spaces directly
        if (!ctype_alnum($c)) {
            $out .= $c;
            $i++;
            continue;
        }

        // Extract word
        $start = $i;
        while ($i < $len && ctype_alnum($input[$i])) {
            $i++;
        }

        $word = substr($input, $start, $i - $start);

        // Get dictionary index
        $id = findOrAdd($dict, $word);

        // Write token
        $out .= '@' . $id;
    }

    return $out;
}


// ---------------------------------------------------------------------
// Decompress @ID tokens back into original text
// ---------------------------------------------------------------------
function decompress(string $compressed, WordDictionary $dict): string {
    $out = '';
    $len = strlen($compressed);
    $i = 0;

    while ($i < $len) {

        $c = $compressed[$i];

        // Token?
        if ($c === '@') {
            $i++;
            $id = 0;

            // Parse digits
            while ($i < $len && ctype_digit($compressed[$i])) {
                $id = $id * 10 + (ord($compressed[$i]) - ord('0'));
                $i++;
            }

            if ($id >= 0 && $id < count($dict->words)) {
                $out .= $dict->words[$id];
            }
        }
        else {
            // Pass punctuation/spaces
            $out .= $c;
            $i++;
        }
    }

    return $out;
}


// ---------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------
$original =
    "this is is a test test compression string string test " .
    "this is a test compression";

$dict = new WordDictionary();

$compressed = compress($original, $dict);
$decompressed = decompress($compressed, $dict);

echo "Original:      \"$original\"\n";
echo "Compressed:    \"$compressed\"\n";
echo "Decompressed:  \"$decompressed\"\n\n";

echo "Dictionary:\n";
foreach ($dict->words as $i => $word) {
    echo "  @$i => $word\n";
}



/*
run:

Original:      "this is is a test test compression string string test this is a test compression"
Compressed:    "@0 @1 @1 @2 @3 @3 @4 @5 @5 @3 @0 @1 @2 @3 @4"
Decompressed:  "this is is a test test compression string string test this is a test compression"

Dictionary:
  @0 => this
  @1 => is
  @2 => a
  @3 => test
  @4 => compression
  @5 => string

*/

 



answered Jul 31 by avibootz

Related questions

...