#include #include #include #include const int KEY_COUNT = 26; const int SIZE_OF_KEYS = sizeof(int) * KEY_COUNT; const int X[KEY_COUNT] = {85, 123, 161, 199, 237, 275, 313, 351, 389, 427, 95, 133, 171, 209, 247, 285, 324, 362, 400, 122, 160, 198, 236, 275, 313, 351}; const int DISTANCE[KEY_COUNT][KEY_COUNT] = {{0, 38, 76, 114, 152, 190, 228, 266, 304, 342, 40, 62, 94, 130, 167, 204, 242, 280, 317, 87, 109, 138, 170, 206, 241, 277}, {38, 0, 38, 76, 114, 152, 190, 228, 266, 304, 48, 40, 62, 94, 130, 167, 205, 242, 280, 79, 87, 109, 138, 171, 206, 241}, {76, 38, 0, 38, 76, 114, 152, 190, 228, 266, 77, 48, 40, 62, 94, 130, 168, 205, 242, 88, 79, 87, 109, 139, 171, 206}, {114, 76, 38, 0, 38, 76, 114, 152, 190, 228, 111, 77, 48, 40, 62, 94, 131, 168, 205, 110, 88, 79, 87, 110, 139, 171}, {152, 114, 76, 38, 0, 38, 76, 114, 152, 190, 147, 111, 77, 48, 40, 62, 95, 131, 168, 140, 110, 88, 79, 88, 110, 139}, {190, 152, 114, 76, 38, 0, 38, 76, 114, 152, 184, 147, 111, 77, 48, 40, 63, 95, 131, 172, 140, 110, 88, 79, 88, 110}, {228, 190, 152, 114, 76, 38, 0, 38, 76, 114, 221, 184, 147, 111, 77, 48, 41, 63, 95, 207, 172, 140, 110, 88, 79, 88}, {266, 228, 190, 152, 114, 76, 38, 0, 38, 76, 259, 221, 184, 147, 111, 77, 47, 41, 63, 242, 207, 172, 140, 110, 88, 79}, {304, 266, 228, 190, 152, 114, 76, 38, 0, 38, 297, 259, 221, 184, 147, 111, 76, 47, 41, 278, 242, 207, 172, 139, 110, 88}, {342, 304, 266, 228, 190, 152, 114, 76, 38, 0, 334, 297, 259, 221, 184, 147, 110, 76, 47, 315, 278, 242, 207, 171, 139, 110}, {40, 48, 77, 111, 147, 184, 221, 259, 297, 334, 0, 38, 76, 114, 152, 190, 229, 267, 305, 48, 76, 110, 147, 184, 222, 259}, {62, 40, 48, 77, 111, 147, 184, 221, 259, 297, 38, 0, 38, 76, 114, 152, 191, 229, 267, 41, 48, 76, 110, 148, 184, 222}, {94, 62, 40, 48, 77, 111, 147, 184, 221, 259, 76, 38, 0, 38, 76, 114, 153, 191, 229, 63, 41, 48, 76, 111, 148, 184}, {130, 94, 62, 40, 48, 77, 111, 147, 184, 221, 114, 76, 38, 0, 38, 76, 115, 153, 191, 96, 63, 41, 48, 77, 111, 148}, {167, 130, 94, 62, 40, 48, 77, 111, 147, 184, 152, 114, 76, 38, 0, 38, 77, 115, 153, 131, 96, 63, 41, 49, 77, 111}, {204, 167, 130, 94, 62, 40, 48, 77, 111, 147, 190, 152, 114, 76, 38, 0, 39, 77, 115, 168, 131, 96, 63, 41, 49, 77}, {242, 205, 168, 131, 95, 63, 41, 47, 76, 110, 229, 191, 153, 115, 77, 39, 0, 38, 76, 206, 169, 132, 97, 63, 41, 48}, {280, 242, 205, 168, 131, 95, 63, 41, 47, 76, 267, 229, 191, 153, 115, 77, 38, 0, 38, 243, 206, 169, 132, 96, 63, 41}, {317, 280, 242, 205, 168, 131, 95, 63, 41, 47, 305, 267, 229, 191, 153, 115, 76, 38, 0, 281, 243, 206, 169, 131, 96, 63}, {87, 79, 88, 110, 140, 172, 207, 242, 278, 315, 48, 41, 63, 96, 131, 168, 206, 243, 281, 0, 38, 76, 114, 153, 191, 229}, {109, 87, 79, 88, 110, 140, 172, 207, 242, 278, 76, 48, 41, 63, 96, 131, 169, 206, 243, 38, 0, 38, 76, 115, 153, 191}, {138, 109, 87, 79, 88, 110, 140, 172, 207, 242, 110, 76, 48, 41, 63, 96, 132, 169, 206, 76, 38, 0, 38, 77, 115, 153}, {170, 138, 109, 87, 79, 88, 110, 140, 172, 207, 147, 110, 76, 48, 41, 63, 97, 132, 169, 114, 76, 38, 0, 39, 77, 115}, {206, 171, 139, 110, 88, 79, 88, 110, 139, 171, 184, 148, 111, 77, 49, 41, 63, 96, 131, 153, 115, 77, 39, 0, 38, 76}, {241, 206, 171, 139, 110, 88, 79, 88, 110, 139, 222, 184, 148, 111, 77, 49, 41, 63, 96, 191, 153, 115, 77, 38, 0, 38}, {277, 241, 206, 171, 139, 110, 88, 79, 88, 110, 259, 222, 184, 148, 111, 77, 48, 41, 63, 229, 191, 153, 115, 76, 38, 0}}; const int DEFAULT_PERMUTATION[KEY_COUNT] = {0, 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}; bool used[KEY_COUNT]; struct element { int index[KEY_COUNT]; int effort; }; inline void swap(int &a, int &b) { int temp = a; a = b; b = temp; } inline int min(int a, int b) { if(a <= b) return a; return b; } int better(int n, int *s, int index[KEY_COUNT], int best_so_far) { int pos = 1, current_left = index[s[0]], current_right, i, next_index, result = 0; while(pos < n && X[index[s[pos - 1]]] == X[index[s[pos]]]) pos++; current_right = index[s[pos]]; if(X[current_left] > X[current_right]) swap(current_left, current_right); for(i = 1; i < n; i++) { next_index = index[s[i]]; if(DISTANCE[current_left][next_index] <= DISTANCE[current_right][next_index] && X[next_index] < X[current_right]) { result += DISTANCE[current_left][next_index]; current_left = next_index; } else { result += DISTANCE[current_right][next_index]; current_right = next_index; } if(result >= best_so_far) return best_so_far; } return result; } int effort(int n, int *s, int index[KEY_COUNT]) { int pos = 1, current_left = index[s[0]], current_right, i, next_index, result = 0; while(pos < n && X[index[s[pos - 1]]] == X[index[s[pos]]]) pos++; current_right = index[s[pos]]; if(X[current_left] > X[current_right]) swap(current_left, current_right); for(i = 1; i < n; i++) { next_index = index[s[i]]; if(DISTANCE[current_left][next_index] <= DISTANCE[current_right][next_index] && X[next_index] < X[current_right]) { result += DISTANCE[current_left][next_index]; current_left = next_index; } else { result += DISTANCE[current_right][next_index]; current_right = next_index; } } return result; } int final_effort(int n, int *s, int index[KEY_COUNT], int second_hand) { int current_left = index[s[0]], current_right = second_hand, i, next_index, result = 0; if(X[current_right] < X[current_left]) swap(current_left, current_right); for(i = 1; i < n; i++) { next_index = index[s[i]]; if(DISTANCE[current_left][next_index] <= DISTANCE[current_right][next_index] && X[current_right] > X[next_index]) { result += DISTANCE[current_left][next_index]; current_left = next_index; } else { result += DISTANCE[current_right][next_index]; current_right = next_index; } } return result; } void random_element(int n, int *s, element &result) { int i; memcpy(result.index, DEFAULT_PERMUTATION, SIZE_OF_KEYS);; for (i = KEY_COUNT - 1; i > 0; i--) swap(result.index[rand() % (i + 1)], result.index[i]); result.effort = effort(n, s, result.index); } void keyboard(int index[KEY_COUNT], char *result) { int i; for(i = 0; i < KEY_COUNT; i++) result[index[i]] = i + 'a'; result[KEY_COUNT] = '\0'; } int main() { clock_t start = clock(); freopen("keyboard.in", "r", stdin); freopen("keyboard.out", "w", stdout); int c_used = 0, n, nu, *su, temp_current_index[KEY_COUNT], i, j, best_j, second_best_j, min_effort = 1000000, best_index[KEY_COUNT], best_g, second_best_g, d_effort, possible[KEY_COUNT * (KEY_COUNT - 1) / 2][2], end = start + 2900; char result[KEY_COUNT + 1], *s; element current, current2; scanf("%d", &n); s = new char[n + 1]; scanf("%s", s); su = new int[n]; nu = 1; su[0] = s[0] - 'a'; for(i = 0; i < n; i++) { if(!used[s[i] - 'a']) c_used++; used[s[i] - 'a'] = true; } int possible_c = 0; for(i = 0; i < KEY_COUNT; i++) for(j = i + 1; j < KEY_COUNT; j++) if(used[i] || used[j]) { possible[possible_c][0] = i; possible[possible_c++][1] = j; } for(i = 1; i < n; i++) if(su[nu - 1] != s[i] - 'a') su[nu++] = s[i] - 'a'; int temp, mc; while(clock() <= end) { random_element(nu, su, current); random_element(nu, su, current2); for(i = 0; i < 100; i++) { mc = min(current.effort, current2.effort); best_g = mc; second_best_g = 1000000; for(j = 0; j < possible_c; j++) { temp = current.index[possible[j][0]]; current.index[possible[j][0]] = current.index[possible[j][1]]; current.index[possible[j][1]] = temp; d_effort = effort(nu, su, current.index); if(best_g >= d_effort) { second_best_g = best_g; best_g = d_effort; second_best_j = best_j; best_j = j; } else if(second_best_g >= d_effort) { second_best_g = d_effort; second_best_j = j; } current.index[possible[j][1]] = current.index[possible[j][0]]; current.index[possible[j][0]] = temp; } if(nu <= 100) for(j = 0; j < possible_c; j++) { temp = current2.index[possible[j][0]]; current2.index[possible[j][0]] = current2.index[possible[j][1]]; current2.index[possible[j][1]] = temp; d_effort = effort(nu, su, current2.index); if(best_g >= d_effort) { second_best_g = best_g; best_g = d_effort; second_best_j = best_j; best_j = -j - 1; } else if(second_best_g >= d_effort) { second_best_g = d_effort; second_best_j = -j - 1; } current2.index[possible[j][1]] = current2.index[possible[j][0]]; current2.index[possible[j][0]] = temp; } if(best_g == mc) break; memcpy(temp_current_index, current.index, SIZE_OF_KEYS); if(best_j >= 0) swap(current.index[possible[best_j][0]], current.index[possible[best_j][1]]); else { memcpy(current.index, current2.index, SIZE_OF_KEYS); swap(current.index[possible[-best_j - 1][0]], current.index[possible[-best_j - 1][1]]); } if(second_best_j >= 0) { memcpy(current2.index, temp_current_index, SIZE_OF_KEYS); swap(current2.index[possible[second_best_j][0]], current2.index[possible[second_best_j][1]]); } else swap(current2.index[possible[-second_best_j - 1][0]], current2.index[possible[-second_best_j - 1][1]]); current.effort = best_g; current2.effort = second_best_g; } if(min_effort > best_g) { min_effort = best_g; memcpy(best_index, current.index, SIZE_OF_KEYS); } } keyboard(best_index, result); int left = best_index[su[0]], c_effort, best_c_effort = 1000000, best_i; for(i = 0; i < KEY_COUNT; i++) if(X[i] != X[left]) { c_effort = final_effort(nu, su, best_index, i); if(best_c_effort > c_effort) { best_c_effort = c_effort; best_i = i; } } if(X[left] > X[best_i]) swap(left, best_i); printf("%s\n%d %d\n", result, left + 1, best_i + 1); return 0; }