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:
View Code
给出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
相关文章推荐
- hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)2015 Multi-University Training Contest 10
- vs2010下配置CUDA出现kernel launch failed问题,内核无效
- Windows Server 2012如何部署Domain Controller
- WinMain与wWinMain,win32的字符集问题
- RAID
- hdu 3635 Dragon Balls(加权并查集)2010 ACM-ICPC Multi-University Training Contest(19)
- INSTALL_FAILED_OLDER_SDK
- INSTALL_FAILED_INSUFFICIENT_STORAGE
- 画布Canvas与画笔Paint
- retain,copy,assign,strong,weak,autorelease,nonatomic,atomic等得使用及区别
- POJ - 3846 Mountain Road 动归
- cassandra中对节点失败与否的探测方法, the Phi accrual Failure Dector,附论文
- 血族 第一季 The Strain Season 1 (2014)
- 模仿Airbnb的悬浮搜索框动画
- pygal and matplotlib(again)
- org.hibernate.LazyInitializationException: failed to lazily initialize a collection..的解决方案
- Rails - 将日期格式字符串转换为秒整数
- 什么是领域驱动设计(Domain Driven Design)?
- raid
- TIME_WAIT 太多的解决办法