#include using namespace std; const int kMaxN = 1e4 + 7; const unsigned long long base = 257; void read(int &t, int &n, vector &words); int max_overlap(const string &lvalue, const string &rvalue); string turn_into_single_word(vector>> &pos, vector &starts, int n, vector words); void make_a_grid(vector> &directions, string word){ int break_pos = -1; pair curr = {0, 0}; for(int i = 1; i < word.size(); ++i){ if((curr.first + 2) * (word.size() - i + curr.second) < 1000000 && i - 2 > break_pos && i >= 2 && word[i] == word[i - 2]){ directions.push_back({0, -1}); curr.second -= 1; int idx = 1; while(i + idx < word.size() && i - 2 - idx > break_pos && word[i + idx] == word[i - 2 - idx]){ directions.push_back({0, -1}); curr.second += 1; ++idx; } i += idx; if(i < word.size()){ directions.push_back({1, 0}); curr.first += 1; } break_pos = i - 1; continue; } else{ directions.push_back({0, 1}); curr.second += 1; } } } int main(){ int t, n; vector words; read(t, n, words); vector>> pos; vector starts; string word = turn_into_single_word(pos, starts, n, words); vector> directions; make_a_grid(directions, word); int min_x = 0, min_y = 0, max_x = 0, max_y = 0; int curr_x = 0, curr_y = 0; for(pair change: directions){ curr_x += change.first; curr_y += change.second; min_x = min(curr_x, min_x); min_y = min(curr_y, min_y); max_x = max(curr_x, max_x); max_y = max(curr_y, max_y); } vector grid(max_x - min_x + 1, string(max_y - min_y + 1, '#')); curr_x = -min_x, curr_y = -min_y; vector> curr_pos; curr_pos.push_back({0, 0}); grid[curr_x][curr_y] = word[0]; for(int i = 1; i < word.size(); ++i){ curr_x += directions[i - 1].first; curr_y += directions[i - 1].second; grid[curr_x][curr_y] = word[i]; curr_pos.push_back({curr_x, curr_y}); } cout << max_y - min_y + 1 << " " << max_x - min_x + 1 << "\n"; for(int i = 0; i < max_x - min_x + 1; ++i){ for(int j = 0; j < max_y - min_y + 1; ++j){ cout << grid[i][j]; } cout << "\n"; } while((max_y - min_y + 1) * (max_x - min_x + 1) >= 1000000); for(int i = 0; i < n; ++i){ cout << curr_pos[starts[i]].second << " " << curr_pos[starts[i]].first << " "; for(int j = starts[i]; j < starts[i] + words[i].size() - 1; ++j){ if(directions[j].first == 1) cout << "D"; else if(directions[j].first == -1) cout << "U"; else if(directions[j].second == 1) cout << "R"; else cout << "L"; } cout << "\n"; } } string turn_into_single_word(vector>> &pos, vector &starts, int n, vector words){ vector> overlap(n, vector(n)); set > overlaps; pos.resize(n); for(int i = 0; i < n; ++i) pos[i].push_back({0, i}); for(int i = 0; i < n; ++i){ for(int j = 0; j < n; ++j){ if(i == j) continue; overlap[i][j] = max_overlap(words[i], words[j]); overlaps.insert(array{overlap[i][j], i, j}); } } int cnt = n; while(cnt != 1){ auto x = *overlaps.rbegin(); overlaps.erase(x); int l = x[1], r = x[2]; for(int i = 0; i < cnt; ++i){ if(i != l){ overlaps.erase(array{overlap[i][l], i, l}); overlaps.erase(array{overlap[l][i], l, i}); } if(i != r && i != l){ overlaps.erase(array{overlap[i][r], i, r}); overlaps.erase(array{overlap[r][i], r, i}); } } if(l > r){ swap(pos[l], pos[r]); swap(words[l], words[r]); swap(l, r); } for(int i = 0; i < pos[r].size(); ++i) pos[l].push_back({pos[r][i].first + words[l].size() - x[0], pos[r][i].second}); for(int i = x[0]; i < words[r].size(); ++i) words[l] += words[r][i]; --cnt; swap(pos[cnt], pos[r]); swap(words[cnt], words[r]); for(int i = 0; i < cnt; ++i){ if(i == l) continue; overlap[i][l] = max_overlap(words[i], words[l]); overlaps.insert(array{overlap[i][l], i, l}); overlap[l][i] = max_overlap(words[l], words[i]); overlaps.insert(array{overlap[l][i], l, i}); } if(r < cnt){ for(int i = 0; i < cnt; ++i){ if(i == r || i == l) continue; overlaps.erase(array{overlap[i][cnt], i, cnt}); overlap[i][r] = max_overlap(words[i], words[r]); overlaps.insert(array{overlap[i][r], i, r}); overlaps.erase(array{overlap[cnt][i], cnt, i}); overlap[r][i] = max_overlap(words[r], words[i]); overlaps.insert(array{overlap[r][i], r, i}); } } } starts.resize(n); for(int i = 0; i < n; ++i) starts[pos[0][i].second] = pos[0][i].first; return words[0]; } int max_overlap(const string &lvalue, const string &rvalue){ int mn = min(lvalue.size(), rvalue.size()); int ret = 0; unsigned long long l_hash = 0, r_hash = 0, power = 1; for(int i = 0; i < mn; ++i){ l_hash *= base; l_hash += lvalue[lvalue.size() - i - 1]; r_hash += power * rvalue[i]; power *= base; if(l_hash == r_hash) ret = max(ret, i + 1); } return ret; } void read(int &t, int &n, vector &words){ ios::sync_with_stdio(false); cin.tie(NULL); freopen("crossword.in", "r", stdin); freopen("crossword.out", "w", stdout); cin >> t; cin >> n; words.resize(n); for(int i = 0; i < n; ++i) cin >> words[i]; }