[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher L(kmp扩展)

来源:互联网 发布:etl算法 编辑:程序博客网 时间:2024/05/16 11:33

Link:https://vjudge.net/contest/70325#problem/L

题意:第一行字符串是字母加密表,The first line of each test case is the conversion table S. S[i] is the ith latin letter's cryptographic letter. 

第二行字符串是密文+明文(明文有可能是不完整的,甚至可能没有)。叫你补完整个密文+明文且最短输出。

思路: 我们知道第二行密文>=明文,所以最好的情况,第二行一半是密文,一半是明文。最坏的情况,是第二行全是密文。

我们知道第二行的前一半肯定是密文,第二行由(密文+明文)组成,我们把第二行直接加密成串T,T(未知的串+密文)。

发现了没,原串中明文部分被加密成密文成为T的后缀,那么我们直接从T的一半往后找到位置i,使得以i开头的后缀为原串的前缀。那这个位置之前就是最小密文.


#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=1e5+10;char mode[maxn];char str[maxn];int extend[maxn];int nextt[maxn];void getNext(char mode[],int next[],int modeLen){int a=0,p=0;nextt[0]=modeLen;for(int i=1;i<modeLen;i++){if(i>=p||i+nextt[i-a]>=p){if(i>=p)p=i;while(p<modeLen && mode[p]==mode[p-i])p++;nextt[i]=p-i;a=i;}else nextt[i]=nextt[i-a];}}void getExtend(char str[],int strLen,int extend[],char mode[],int modeLen){getNext(mode,nextt,modeLen);int a=0,p=0,sum=0;for(int i=0;i<strLen;i++){if(i>=p || i+nextt[i-a]>=p){   if(i>=p) p=i;   while(p<strLen && p-i<modeLen && str[p]==mode[p-i])      p++; extend[i]=p-i;a=i;}else extend[i]=nextt[i-a];}}char hashh[maxn];char temp[maxn];int main(){int T;scanf("%d",&T);while(T--){scanf("%s",temp);scanf("%s",mode);for(int i=0,j=strlen(temp);i<j;i++) hashh[temp[i]]='a'+i;  //解密 for(int i=0,j=strlen(mode);i<j;i++) {str[i]=temp[mode[i]-'a']; //加密 if(i==j-1) str[j]=0;}//puts(str);int strLen=strlen(str);int modeLen=strlen(mode);getExtend(str,strLen,extend,mode,modeLen);//for(int i=0;i<strLen;i++) printf("%d ",extend[i]);int mid;if(strLen%2==0)mid=strLen/2;else mid=strLen/2+1;int j;for(j=mid;j<strLen;j++)if(extend[j]+j==strLen)break;for(int i=0;i<j;i++) printf("%c",mode[i]);for(int i=0;i<j;i++) printf("%c",hashh[mode[i]]);printf("\n");}}


阅读全文
0 0
原创粉丝点击