您的位置:首页 > 大数据 > 人工智能

hdu 4300 Clairewd’s message(kmp/扩展kmp)

2015-08-21 17:12 417 查看
题意:真难懂。。

给出26个英文字母的加密表,明文中的'a'会转为加密表中的第一个字母,'b'转为第二个,...依次类推。

然后第二行是一个字符串(str1),形式是密文+明文,其中密文一定完整,而明文可能不完整(也可能没有)。

求出最短的完整的字符串(密文+明文)。

思路:

1.用kmp来做:

首先肯定的是,给定的串中明文长度一定小于等于密文。也就是说明文长度小于等于总长的一半。

于是,取总长的后一半作为主串,然后把串反翻译一遍得到str2,然后用str2与str1的后一半进行匹配。首次把str1的后一半匹配完的位置即是给定的串中明文开始的位置。

因为是首次,所以保证了前面的密文长度最小,即总长度最小。

然后输出密文+明文,即可。

2.用扩展kmp来做:

//next[i]:x[i...m-1]与x[0...m-1]的最长公公前缀

//extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀

可以用extend数组,根据它的意义,str1作为y,str2作为x,当 i+extend[i]==len1时代表y中的从i到结尾均与x的开头匹配,如果此时i大于串长度的一半,则满足条件。

此时的i即为实际密文(明文)的长度,然后按要求输出答案即可。

kmp:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define MaxSize 100005

int _next[MaxSize],extend[MaxSize];

//扩展kmp
//next[i]:x[i...m-1]与x[0...m-1]的最长公公前缀
//extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀
void pre_EKMP(char x[],int m,int _next[]){
_next[0]=m;
int j=0;
while(j+1<m&&x[j]==x[j+1])j++;
_next[1]=j;
int k=1;
for(int i=2;i<m;i++){
int p=_next[k]+k-1;
int L=_next[i-k];
if(i+L<p+1)_next[i]=L;
else{
j=max(0,p-i+1);
while(i+j<m&&x[i+j]==x[j])j++;
_next[i]=j;
k=i;
}
}
}

void EKMP(char x[],int m,char y[],int n,int _next[],int extend[]){
pre_EKMP(x,m,_next);
int j=0;
while(j<n&&j<m&&x[j]==y[j])j++;
extend[0]=j;
int k=0;
for(int i=1;i<n;i++){
int p=extend[k]+k-1;
int L=_next[i-k];
if(i+L<p+1)extend[i]=L;
else{
j=max(0,p-i+1);
while(i+j<n&&j<m&&y[i+j]==x[j])j++;
extend[i]=j;
k=i;
}
}
}

int main(){
char str[27],str1[MaxSize],str2[MaxSize];
char cstr[27];//密文->明文
int t,i,j,len1,len11,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]='\0';
EKMP(str2,len1,str1,len1,_next,extend);
len11=(len1+1)/2;//假设串中密文长度
for(i=len11;i<len1;++i)//从一半+1开始看,因为密文长度大于等于一半
if(i+extend[i]==len1)break;//此时i为实际密文(明文)长度
printf("%s",str1);
for(j=len1-i;j<i;++j){
printf("%c",str2[j]);
}
printf("\n");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: