1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <cstdio>
#include <queue>
#include <unordered_map>
#include <vector>

const char ROW = 'R';
const char COLUMN = 'K';
const int NN = 2020;
char data[NN][NN];

struct Command {
  char type, color;
  int number;
};

Command mk_cmd(char type, int number, char color) {
  Command c = {.type = type, .color = color, .number = number};
  return c;
}

void increment(std::unordered_map<char, int> &map, char key) {
  if (map.contains(key)) {
    map[key] += 1;
  } else {
    map[key] = 1;
  }
}

void decrease(std::unordered_map<char, int> &map, char key) {
  map[key] -= 1;
  if (map[key] == 0) {
    map.erase(key);
  }
}

int main() {
  int Rows, Columns;
  scanf("%d%d", &Rows, &Columns);

  for (int r = 0; r < Rows; ++r) {
    scanf("%s", data[r]);
  }

  std::vector<std::unordered_map<char, int>> row_data;
  std::vector<std::unordered_map<char, int>> col_data;
  for (int r = 0; r < Rows; ++r) {
    row_data.push_back(std::unordered_map<char, int>());
  }
  for (int c = 0; c < Columns; ++c) {
    col_data.push_back(std::unordered_map<char, int>());
  }

  std::queue<Command> queue;
  std::vector<Command> res;

  for (int r = 0; r < Rows; ++r) {
    for (int c = 0; c < Columns; ++c) {
      increment(row_data[r], data[r][c]);
      increment(col_data[c], data[r][c]);
    }
  }

  int idx = 0;
  for (auto &rd : row_data) {
    if (rd.size() == 1) {
      queue.push(mk_cmd(ROW, idx, rd.begin()->first));
      rd.clear();
    }
    ++idx;
  }
  idx = 0;
  for (auto &cd : col_data) {
    if (cd.size() == 1) {
      queue.push(mk_cmd(COLUMN, idx, cd.begin()->first));
      cd.clear();
    }
    ++idx;
  }

  while (!queue.empty()) {
    Command exec = queue.front();
    queue.pop();
    res.push_back(exec);

    if (exec.type == ROW) {
      int idx = 0;
      for (auto &cd : col_data) {
        if (!cd.empty()) {
          decrease(cd, exec.color);
          if (cd.size() == 1) {
            queue.push(mk_cmd(COLUMN, idx, cd.begin()->first));
            cd.clear();
          }
        }
        ++idx;
      }
    } else {
      int idx = 0;
      for (auto &rd : row_data) {
        if (!rd.empty()) {
          decrease(rd, exec.color);
          if (rd.size() == 1) {
            queue.push(mk_cmd(ROW, idx, rd.begin()->first));
            rd.clear();
          }
        }
        ++idx;
      }
    }
  }

  printf("%d\n", (int) res.size());
  for (auto it = res.rbegin(); it != res.rend(); ++it) {
    printf("%c %d %c\n", it->type, it->number + 1, it->color);
  }

  return 0;
}