标签:OLE hdu efi after graphic 文件 method mon stream
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10376 Accepted Submission(s): 3709
题意:有一份文件,原文由密文和明文组成,前面一部分是密文,后面一部分是明文,密文可以通过转换规则(26个字母,每个字母变成它所在的下标的字母qwerty->abcdef)表示成明文,但那个人接到这个文件后不知道从哪里开始是明文,所以你要帮忙还原一下,
如果后面明文比密文少,你就将明文补全
所以这题的关键就是找到密文和明文交界的位置,
因为密文是完整的给出的,明文可能不完整,所以明文开始的位置一定是 >= len/2+len%2 的(数据是从0开始存,所以可以取等),因为如果长度为奇数个要从后一位开始。
对原文用哈希处理两次,第一次都按密文转换规则处理(p1),第二次按明文处理(p2),之后从中间位置开始,不断比较两者哈希值,当相等是就找到交界位置,若找不到,就说明只有密文
#include<iostream> #include<string.h> #include<string> #include<math.h> #define ull unsigned long long using namespace std; string str,s; ull num[33]; ull p1[100005],p2[100005],pow1[100005];//存储哈希值 ull n; void init()//计算131的i次方 { pow1[0]=1; for(int i=1;i<=100000;i++) pow1[i]=pow1[i-1]*131; } void hs() { p1[0]=num[str[0]-‘a‘], p2[0]=str[0]-‘a‘; for(int i=1;i<str.length();i++) { p1[i]=p1[i-1]*131+num[str[i]-‘a‘];//计算原文str的哈希值 p2[i]=p2[i-1]*131+(str[i]-‘a‘);//计算明文的哈希值 } } ull get(ull pp[],ull l,ull r)//pow()函数会溢出 { return pp[r]-pp[l-1]*pow1[r-l+1]; } int main() { cin>>n; init(); while(n--) { cin>>s; cin>>str; for(int i=0;i<26;i++)//先把转换规则表示成[0,25]个数字,输出结果的时候在转换回去 { num[s[i]-‘a‘]=i; } hs(); ull x1,x2,len,flag=0; len=str.length(); x1=len/2+len%2;//原文中第一个明文的下标 for(int i=x1;i<len;i++)//通过比较哈希值,找到原文的第一个明文下标 { ull y1,y2; x2=len-1-i; y1=get(p1,0,x2); y2=get(p2,i,len-1); if(y1==y2)//密文与明文的哈希值相等 { flag=1; x1=i; break; } } if(flag==0)//原文都是密文 x1=len; for(int i=0;i<x1;i++)//输出密文 cout<<str[i]; for(int i=0;i<x1;i++)//把密文翻译成明文输出 printf("%c",num[str[i]-‘a‘]+‘a‘); cout<<endl; } }
hdu 4300 Clairewd’s message 字符串哈希
标签:OLE hdu efi after graphic 文件 method mon stream
原文地址:https://www.cnblogs.com/-citywall123/p/10841081.html