Alex's Anthology of Algorithms Common Code for Contests in Concise C++
Strings / Encoding and Compression

3.8.2 Run-Length Encoding

3-Strings/3.8.2_Run-Length_Encoding.cpp

Encodes consecutive equal characters as (character, count) runs. Run-length encoding is a simple lossless compression technique that works well when strings contain long repeated blocks and poorly when repetitions are rare.

The representation below stores runs in a vector of pairs rather than formatting them as a string. This avoids ambiguity when the original text contains digits or separator characters.

  • run_length_encode(s) returns the sequence of runs in string s.
  • run_length_decode(runs) reconstructs the original string from a sequence of runs.

Implementation

#include <string>
#include <utility>
#include <vector>
using std::string;

std::vector<std::pair<char, int>> run_length_encode(const string &s) {
  std::vector<std::pair<char, int>> res;
  for (char c : s) {
    if (res.empty() || res.back().first != c) {
      res.emplace_back(c, 1);
    } else {
      res.back().second++;
    }
  }
  return res;
}

string run_length_decode(const std::vector<std::pair<char, int>> &runs) {
  string res;
  for (auto [c, count] : runs) {
    res.append(count, c);
  }
  return res;
}

Example Usage

#include <cassert>
using namespace std;

int main() {
  string s = "aaabccccdd";
  vector<pair<char, int>> runs = run_length_encode(s);
  assert((runs == vector<pair<char, int>>{{'a', 3}, {'b', 1}, {'c', 4}, {'d', 2}}));
  assert(run_length_decode(runs) == s);
  assert(run_length_encode("").empty());
  assert(run_length_decode({}) == "");
  assert((run_length_encode("z") == vector<pair<char, int>>{{'z', 1}}));
  return 0;
}