hdu 4300 Clairewd’s message(kmp/扩展kmp)
题意:真难懂。。
给出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]; void GetNext(char t[]){//求next数组
int j,k,len;
j=;
k=-;
_next[]=-;
len=strlen(t);
while(j<len){
if(k==-||t[j]==t[k]){
++j;
++k;
_next[j]=k;//此句可由优化替代
/*优化(仅保证求KMPIndex时可用。谨慎使用。)
if(t[j]!=t[k])next[j]=k;
else next[j]=next[k];
*/
}
else k=_next[k];
}
} int KMPIndex(char s[],char t[]){//求子串首次出现在主串中的位置
int i,j,lens,lent;
i=j=;
lens=strlen(s);
lent=strlen(t); while(i<lens&&j<lent){
if(j==-||s[i]==t[j]){
++i;
++j;
}
else j=_next[j];
}
//if(j>=lent)return i-lent;
//else return -1;
return j;
} int main(){
char str[],str1[MaxSize],str2[MaxSize];
char cstr[];//密文->明文
int t,i,len1,len11,num;
scanf("%d",&t); while(t--){
scanf("%s%s",str,str1);
for(i=;i<;++i)
cstr[str[i]-'a']='a'+i;
len1=strlen(str1);//
for(i=;i<len1;++i)
str2[i]=cstr[str1[i]-'a'];
str2[i]='\0';
GetNext(str2);//求子串的next数组
len11=len1/;//假设串中明文长度
num=KMPIndex(str1+len1-len11,str2);//串中的明文个数
printf("%s",str1);
len11=len1-num;//实际密文(明文)长度
for(i=num;i<len11;++i){
printf("%c",str2[i]);
}
printf("\n");
}
return ;
}
扩展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[]=m;
int j=;
while(j+<m&&x[j]==x[j+])j++;
_next[]=j;
int k=;
for(int i=;i<m;i++){
int p=_next[k]+k-;
int L=_next[i-k];
if(i+L<p+)_next[i]=L;
else{
j=max(,p-i+);
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=;
while(j<n&&j<m&&x[j]==y[j])j++;
extend[]=j;
int k=;
for(int i=;i<n;i++){
int p=extend[k]+k-;
int L=_next[i-k];
if(i+L<p+)extend[i]=L;
else{
j=max(,p-i+);
while(i+j<n&&j<m&&y[i+j]==x[j])j++;
extend[i]=j;
k=i;
}
}
} int main(){
char str[],str1[MaxSize],str2[MaxSize];
char cstr[];//密文->明文
int t,i,j,len1,len11,num;
scanf("%d",&t); while(t--){
scanf("%s%s",str,str1);
for(i=;i<;++i)
cstr[str[i]-'a']='a'+i;
len1=strlen(str1);
for(i=;i<len1;++i)
str2[i]=cstr[str1[i]-'a'];
str2[i]='\0';
EKMP(str2,len1,str1,len1,_next,extend);
len11=(len1+)/;//假设串中密文长度
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 ;
}
hdu 4300 Clairewd’s message(kmp/扩展kmp)的更多相关文章
- HDU 4300 Clairewd’s message(扩展KMP)
思路:extend[i]表示原串以第i開始与模式串的前缀的最长匹配.经过O(n)的枚举,我们能够得到,若extend[i]+i=len且i>=extend[i]时,表示t即为该点之前的串,c即为 ...
- HDU 4300 Clairewd’s message(扩展KMP)题解
题意:先给你一个密码本,再给你一串字符串,字符串前面是密文,后面是明文(明文可能不完成整),也就是说这个字符串由一个完整的密文和可能不完整的该密文的明文组成,要你找出最短的密文+明文. 思路:我们把字 ...
- HDU - 4300 Clairewd’s message (拓展kmp)
HDU - 4300 题意:这个题目好难读懂,,先给你一个字母的转换表,然后给你一个字符串密文+明文,密文一定是全的,但明文不一定是全的,求最短的密文和解密后的明文: 题解:由于密文一定是全的,所以他 ...
- hdu 4300 Clairewd’s message(扩展kmp)
Problem Description Clairewd is a member of FBI. After several years concealing in BUPT, she interce ...
- hdu 4300 Clairewd’s message KMP应用
Clairewd’s message 题意:先一个转换表S,表示第i个拉丁字母转换为s[i],即a -> s[1];(a为明文,s[i]为密文).之后给你一串长度为n<= 100000的前 ...
- hdu 4300 Clairewd’s message 字符串哈希
Clairewd’s message Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- hdu 4300 Clairewd’s message(具体解释,扩展KMP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300 Problem Description Clairewd is a member of FBI. ...
- HDU 4300 Clairewd’s message(KMP+思维)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300 题目大意:题目大意就是给以一段字符xxxxzzz前面x部分是密文z部分是明文,但是我们不知道是从 ...
- HDU 4300 Clairewd's message ( 拓展KMP )
题意 : 给你一个包含26个小写字母的明文密文转换信息字符串str,第一个表示'a'对应的密文是str[0].'b'对应str[1]……以此类推.接下来一行给你一个另一个字符串,这个字符串由密文+明文 ...
随机推荐
- 使用plantuml生成uml图
主要包括以下三步: 一.到http://plantuml.com/download 下载plantuml.jar ,我将这个软件放置到home的/home/munication/WORKM/Progr ...
- JFinal2.0极速开发视频教程发布【转】
原文:http://blog.dreamlu.net/blog/79 目前JFinal越来越火爆,而且使用的公司越来越多.鉴于市面上JFinal的学习资源不多,我们开始基于JFinal2.0录制学习视 ...
- vue之条件渲染
一.v-if v-if指令用于条件的渲染一块内容,当指令的表达式返回true时,内容才会被渲染. <h1 v-if="isshow">要显示么</h1> d ...
- Jetty插件实现热部署(开发时修改文件自动重启Jetty)
在pom.xml文件中配置Jetty插件的参数:scanIntervalSeconds <plugin> <groupId>org.mortbay.jetty</grou ...
- 使用Maven运行Java main的方法(转)
使用Maven运行Java Main的方法(既Java Application项目),可以有如下方式解决: 1.将Maven项目导入到eclipse中,然后直接项目右键[Run As]->[Ja ...
- BUPT复试专题—List(2015)
题目描述 在该LIST上实现3种操作 1.append x在该LIST末尾添加x,x是32位整数 2.pop删除该LIST末尾的数 3.find i寻找第i个数,若i为负数表示寻找倒数第i个数,例如i ...
- svn简单介绍
版本号控制(Revision control)是维护project蓝图的标准做法,能追踪project蓝图从诞生一直到定案的过程.是一种记录若干文件内容变化.以便将来查阅特定版本号修订情况的系统. 能 ...
- 【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement
本blog提供了一个简单的通过JDBC驱动建立JDBC连接例程.并分别通过Statement和PreparedStatement实现对数据库的查询. 在下一篇blog中将重点比較Statement与P ...
- Android studio 升级,不用下载完整版,完美更新到2.0
Android studio 2.0 公布已有一旦时间,据说,速度大大提高了.但是一直没有尝试更新,看到大家相继更新,所以迫不及待就准备更新,但是.更新之路确实异常坎坷.询问度娘,千奇百怪的问题接憧而 ...
- 【转载】C#之C#、.NET Framework、CLR的关系
C#..NET Framework.CLR的关系 很多人没有将C#..NET Framework(.NET框架).CLR(Common Language Runtime,公共语言运行库)这三者之间的关 ...