#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 4;
int n, ci = 0, sol2 = 0;
string name;
vector<pair<int, int> > sol;
struct Node {
  char c;
  int idx, dub;
  map<char, Node*> child;
  Node(char ac, int dubina) {
    c = ac;
    idx = ci;
    dub = dubina;
  }
};
auto root = Node(' ', 0);
vector<int>* vec[2][8 * MAXN];
void dodaj(bool typ, int id) {
  auto cur = &root;
  int cnt = 1;
  for (auto c : name) {
    if (!vec[0][cur->idx]) vec[0][cur->idx] = new vector<int>();
    if (!vec[1][cur->idx]) vec[1][cur->idx] = new vector<int>();
    if ((cur->child)[c] == 0) {
      ci++;
      (cur->child)[c] = new Node(c, cnt);
    }
    cur = (cur->child)[c];
    cur->dub = cnt;
    cnt++;
  }
  if (!vec[0][cur->idx]) vec[0][cur->idx] = new vector<int>();
  if (!vec[1][cur->idx]) vec[1][cur->idx] = new vector<int>();
  vec[typ][cur->idx]->push_back(id);
}
void spoji(int a, int b, int typ) {
  if (vec[typ][a]->size() > vec[typ][b]->size()) {
    swap(a, b);
  }
  auto x = vec[typ][a];
  auto y = vec[typ][b];
  for (auto z : *vec[typ][a]) {
    vec[typ][b]->push_back(z);
  }
  vec[typ][a] = vec[typ][b];
}
void dfs(Node* cur) {
  auto tmp = cur->idx;
  for (auto z : (cur->child)) {
    dfs(z.second);
    spoji(tmp, (z.second)->idx, 0);
    spoji(tmp, (z.second)->idx, 1);
  }
  while (!(vec[0][tmp]->empty() || vec[1][tmp]->empty())) {
    sol.push_back({(vec[0][tmp]->back()), (vec[1][tmp]->back())});
    vec[0][tmp]->pop_back();
    vec[1][tmp]->pop_back();
    sol2 += cur->dub;
  }
}
int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> name;
    dodaj(1, i);
  }
  for (int i = 1; i <= n; i++) {
    cin >> name;
    dodaj(0, -i);
  }
  dfs(&root);
  cout << sol2 << endl;
  for (auto pr : sol) cout << abs(pr.second) << ' ' << abs(pr.first) << endl;
  return 0;
}
