1. 程式人生 > >Clairewd's message /// 字符串hash

Clairewd's message /// 字符串hash

fin work event for 給定 sed sizeof name play

題目大意:

給定字符串s 是26個字母對應的密文字母

給定字符串c1 是 密文+部分原文

原文可能缺損 要求將原文補全輸出

利用s得到密文字母對應的原字母rs

利用rs翻譯c1得到 原文+部分密文c2

由於密文肯定是完整的 此時

c1 完整密文+部分原文

c2 完整原文+部分密文

將兩個字符串hash 若一段字符相等則對應段的hash值也相等

枚舉原文的長度 就可以得到在c1中原文的開始位置len

則此時假設 c1中 n-len+1~n 為原文 則c2中1~len為原文

若此時這兩段字符的hash值相等 則假設成立

技術分享圖片
#include <bits/stdc++.h>
using
namespace std; #define LL long long #define ULL unsigned long long #define INF 0x3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) #define gcd(i,j) __gcd(i,j); const int maxn=1e5+5; const int mod=1e9+7; const
double eps=1e-8; typedef unsigned long long ull; struct hash_table{ ull seed=163; ull Hash[maxn],temp[maxn]; void work(char *s,int n){ temp[0]=1; Hash[0]=0; for(int i=1;i<=n;i++)temp[i]=temp[i-1]*seed; for(int i=1;i<=n;i++)Hash[i]=(Hash[i-1]*seed+(s[i]-a)); } ull
get(int l,int r){ return Hash[r]-Hash[l-1]*temp[r-l+1]; } }h1, h2; char c1[maxn],c2[maxn]; char s[30],rs[30]; int main() { int _; scanf("%d",&_); while(_--) { scanf("%s%s",s,c1+1); inc(i,0,26-1) rs[s[i]-a]=i+a; int n=strlen(c1+1); inc(i,1,n) c2[i]=rs[c1[i]-a]; h1.work(c1,n); h2.work(c2,n); // h1對應的 c1是完整密文+部分原文 // h2對應的 c2是完整原文+部分密文 int ans=n; inc(i,n,n*2-1) { // 枚舉整串的長度 if(i&1) continue; // 奇數長度跳過 int mid=i/2; // 得到此時密文的長度 int len=n-mid; // 再得到部分原文的長度 ULL s1=h1.get(n-len+1,n); // 部分原文的密文 ULL s2=h2.get(1,len); // 部分原文 if(s1==s2) { ans=mid; break; } // 若兩個區間hash值相同 說明兩段字符相同 } inc(i,1,ans) printf("%c",c1[i]); inc(i,1,ans) printf("%c",c2[i]); printf("\n"); } return 0; }
View Code

Clairewd's message /// 字符串hash