• Jzoj2937 监听还原


    Alice和Bob正在悄悄地给对方发信息,信息都是由英文小写字母组成的,他们约定,所有的字母都得经过一个字母表进行变换,以防泄漏。另一方面John却在监听。

    John发现,Alice和Bob通信的时候,总是先发送加密后的密文,然后紧接着发送原文。

    但是Alice和Bob似乎也意识到了似乎有人监听,有时候会随意中断了他们的通信。不过每次都是在发送完密文之后才停止传送的。也就是说,John截获到的信息是密文的全文以及前一部分原文。原文可能一个字符都没有,也可能原文的全文都被截获。

    现在John比较头疼,他虽然已经得到了他们两个人通信的加密字母表,但是分不清楚什么地方是密文和明文的分界线。你能帮他还原回完整的传输内容吗?

    如果有多种可能时,John认为那个最短的信息才是原始的。
    解法,我们将原串和转置后的串分别求hash函数,让后就是枚举分割点O(1)判断相等了,复杂度O(N)
    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define L long long
    using namespace std;
    char s[200010]={0},c[26],r[26];
    L b[100010],h1[100010],h2[100010],n;
    __attribute__((optimize("-O3"))) inline L gH1(int l,int r){ return h1[r]-h1[l-1]*b[r-l+1]; }
    __attribute__((optimize("-O3"))) inline L gH2(int l,int r){ return h2[r]-h2[l-1]*b[r-l+1]; }
    int main(){
    	scanf("%s%s",c,s+1); 
    	*b=1; *h1=*h2=0; n=strlen(s+1);
    	for(int i=0;i<26;++i) r[c[i]-'a']=i;
    	for(int i=1;i<=n;++i){
    		b[i]=b[i-1]*27;
    		h1[i]=h1[i-1]*27+s[i]-'a';
    		h2[i]=h2[i-1]*27+c[s[i]-'a']-'a';
    	}
    	for(int i=n+2+(n&1)>>1;i<=n;++i)
    		if(gH1(1,n-i+1)==gH2(i,n)){
    			int m=i-(n-i+1)-1,l=n-i+1;
    			for(int j=1;j<=m;++j) s[j+n]=r[s[j+l]-'a']+'a';
    			puts(s+1); puts("");return 0;
    		}
    	for(int j=1;j<=n;++j) s[j+n]=r[s[j]-'a']+'a';
    	puts(s+1);
    }


  • 相关阅读:
    ASP.NET编程中非常有用的例子
    打包样式资源
    9.使用类的2个注意点
    面向对象案例
    super必须放到子类this之前
    PHP:根据二维数组中的某个字段进行排序
    Vuex的五个核心属性
    利用按钮控制listview的当前选择项,滚动条跟随动
    c#通过进程名字获取进程路径
    判断客户端是否安装realplayer
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477357.html
Copyright © 2020-2023  润新知