题意:乱七八糟说了一大堆,就是先给你一个长度26的字符串,对应了abcd....xyz,这是一个密码表。然后给你一个字符串,这个字符串是不完整的(完整的应该是前半部分是加密的,后半部分是解密了的),然而,给你的字符串一定是加密的部分+一部分解密的部分(可以是全部,也可以是没有),让你求出最短的完整字符串;
解题思路:考虑给出的字符串加密部分一定全部给出,所以,给出的字符串的一半一定是加密的,所以把这一半先转换好,然后和后缀比一下,求最长的公共前缀,用kmp和拓展kmp都行;
拓展kmp(这里要注意下,如果用这个,那么一定公共前缀一定要等于后缀,也就是next[i]+i>len)
:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<map> #define maxn 100500 using namespace std; char t[maxn]; char word[maxn]; char ans[maxn]; char s[maxn]; int _next[maxn]; int tlen; void get_next() { int i=0,j,po; _next[0]=tlen; while(t[i]==t[i+1]&&i+1<tlen) i++; _next[1]=i; po=1; for(int i=2;i<tlen;i++) { if(_next[i-po]+i<_next[po]+po) _next[i]=_next[i-po]; else { j=_next[po]+po-i; if(j<0) j=0; while(i+j<tlen&&t[j]==t[j+i]) j++; _next[i]=j; po=i; } } } int main() { int tt; int y; scanf("%d",&tt); word[0]='a'; for(int i=1;i<26;i++) word[i]=word[i-1]+1; while(tt--) { map<char,char>m; scanf("%s",ans); scanf("%s",t); for(int i=0;i<26;i++) { m[ans[i]]=word[i]; } int len=strlen(t); for(int i=0;i<len;i++) s[i]=t[i]; tlen=len; len=len/2; if(tlen%2==1) len++; for(int i=0;i<len;i++) { t[i]=m[t[i]]; } get_next(); int maxx=0; for(int i=len;i<tlen;i++) { if(_next[i]+i>=tlen) maxx=max(maxx,_next[i]); } //cout<<maxx<<endl; int slen=tlen-maxx; for(int i=0;i<slen;i++) { cout<<s[i]; } for(int i=0;i<slen;i++) { cout<<m[s[i]]; } cout<<endl; } }
kmp:(用·这个就要注意aaa这种情况,就是前后缀重叠了)
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<map> #define maxn 100500 using namespace std; char t[maxn]; char ans[maxn]; char word[maxn]; char s[maxn]; int next1[maxn]; int tlen; void get_next() { int j=0,k=-1;next1[0]=-1; while(j<tlen) { if(t[j]==t[k]||k==-1) next1[++j]=++k; else k=next1[k]; } } int main() { int tt; word[0]='a'; for(int i=1;i<26;i++) word[i]=word[i-1]+1; cin>>tt; while(tt--) { map<char,char>m; cin>>ans; cin>>t; for(int i=0;i<26;i++) { m[ans[i]]=word[i]; } int len=strlen(t); for(int i=0;i<len;i++) s[i]=t[i]; tlen=len;len=len/2; if(tlen%2==1) len++; for(int i=0;i<len;i++) { t[i]=m[t[i]]; } get_next(); int maxx=next1[tlen]; if(maxx>tlen/2) maxx=tlen/2; int slen=tlen-maxx; for(int i=0;i<slen;i++) cout<<s[i]; for(int i=0;i<slen;i++) cout<<m[s[i]]; cout<<endl; } }