To Huffman-code LZSS output you first turn tokens into symbols. Today you map the token stream into two alphabets - literals-and-lengths in one, distances in the other - exactly the split DEFLATE uses.
Convert a token stream into a literal/length symbol stream and a distance symbol stream.
DEFLATE’s insight is to compress the LZSS token stream itself with Huffman coding,
and to do that it needs the tokens as symbols. It uses two alphabets. The
literal/length alphabet packs three things into one code space: values 0..255
are literal bytes, 256 is a special end-of-block marker, and 257 and up are
match lengths (symbol = 257 + (length - MIN_MATCH)). The distance
alphabet holds match offsets.
Splitting this way lets each alphabet get its own Huffman code tuned to its own
statistics - literals and lengths cluster differently from distances. For
ABCABCD the three literals become 65, 66, 67, the Match(3, 3) becomes length
symbol 257 in the literal/length stream plus offset 3 in the distance stream,
the last literal is 68, and a closing 256 marks the end. The decoder reads the
literal/length stream and, whenever it hits a length symbol, pulls the next
distance from the distance stream - the two move in lockstep. Real DEFLATE folds
ranges of lengths and distances into shared codes with extra bits; we give each
value its own symbol to keep the numbers exact, a simplification the caveats note.
// literal/length alphabet: 0..255 literals, 256 = end of block,// 257+ = match length (symbol = 257 + (length - MIN_MATCH))// distance alphabet: the raw offset// literal -> litlen += byte// match -> litlen += 257+(len-3); dist += offset// finally append 256 (EOB) to litlen