题意:给出26个字母对应的映射关系,然后给出一行string
其中有密文也有明文,明文部分是不完整的 ,输出可能组成的最短明文
思路:先将(假设整个子串为)暗文全部翻译成明文,然后将翻译后的子串与原串相连接,去匹配最长公共前后缀,这是一种思路(但是会超时)
例如: qwertyuiopasdfghjklzxcvbnm qwertabcde -> jvrkzqwert (转译后) qwertabcdejvrkzqwert 找公共前后缀长度即可 (但是注意其长度不能超过n/2最长明文长度)
所以换一种思路:我们知道密文的长度至少为n/2,先将其转为明文然后再求最长公共前缀位置kmp然后用len减去(也就是直接使用kmp来求解)
或者我们再用扩展kmp的算法,来求得模式串(转译后)与原串(转译前)的最长前缀,从而得到所能匹配的明文部分
kmp代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 100005 int nex[maxn]; void getnext(char t[]){//求next数组 int j,k,len; j=0; k=-1; nex[j]= k; len=strlen(t); while(j<len){ if(k==-1||t[j]==t[k]){ nex[++j] =++k; } else k=nex[k]; } } int kmp(char s[],char t[]){//求子串首次出现在主串中的位置 int i,j,lens,lent; i=j=0; lens=strlen(s); lent=strlen(t); while(i<lens&&j<lent){ if(j==-1||s[i]==t[j]){ ++i; ++j; } else j=nex[j]; } return j; } int main(){ char str[27],str1[maxn],str2[maxn]; char cstr[27];//密文->明文 int t,i,len1,len2,num; scanf("%d",&t); while(t--){ scanf("%s%s",str,str1); for(i=0;i<26;++i) cstr[str[i]-'a']= 'a'+i;//转换 len1=strlen(str1); for(i=0;i<len1;++i) str2[i]=cstr[str1[i]-'a'];//全部转换为明文(假设全部为暗文) str2[i]='