Brief description: http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4300
A table with 26 letters in one-to-one plaintext to ciphertext, and a string a with plaintext + ciphertext (with default value) are provided. The minimum length of A is obtained.
Analysis:
First, I tried to use brute force. Later I found that it was very time-consuming to judge the same strings. TLE had performed several times and finally found that KMP was acceptable. First, I set the first half of a (it must be plain text, this is obvious.) translate it into a secret, then obtain the next array of the new string, iterate the next array of the last letter (see the code for details), and keep moving to the length <= String Length/2 to stop, then we can find the complete a with the smallest length.
#include <cstdio>#define maxn 100010#include <cstring>int T, next[maxn];char table[30], ori[maxn], ans[maxn * 2], copy[maxn], mitoming[30];using namespace std;void get_next(char * pat){ memset(next, 0, sizeof(next)); int patlen = strlen(pat); int p = -1, t = 0; next[0] = -1; while(t < patlen){ if(p == -1 || pat[t] == pat[p]){ t ++, p ++, next[t] = p; // (pat[t] == pat[p]) ? next[p] : p; }else{ p = next[p]; } }}int main(){ scanf("%d",&T); while(T --){ scanf("%s %s", table, ori); int len = strlen(ori); int id = len; // memset(copy,0,sizeof(copy)); memset(ans,0,sizeof(ans)); strcpy(copy, ori); for(int i = 0; i < 26; i ++){ mitoming[table[i] - 'a'] = 'a' + i; } mitoming[26] = '\0'; for(int i = 0; i < len / 2; i ++){ copy[i] = mitoming[copy[i] - 'a']; }// printf("%s be", copy); get_next(copy);// printf("%s af", copy);// printf("%d kaka \n", strlen(copy));// for(int i = 0; i < strlen(copy); i ++)// printf("%d !! ", next[i]);// puts(""); int i = len - 1, j; while(next[i] >= len / 2){ i = next[i]; }// printf("%d be \n", i); if(next[i] == 0) id = len; else id = len - 1 - next[i];// printf("%d\n", id); for(i = 0; i < id; i ++){ ans[i] = ori[i]; ans[i + id] = mitoming[ori[i]- 'a']; } ans[i + id] = '\0'; printf("%s\n", ans); } return 0;}