並查集 HAOI破譯密文

2021-09-02 13:48:21 字數 2849 閱讀 8131

【問題描述】

資訊的明文是由0利1組成的非空序列。但在網路通訊中,為了資訊的安全性,常對明文進行加密,用密文進行傳輸。密文是由0、1和若干個密碼字母組成,每個密碼字母代表不同的01串,例如,密文=011a0bf00a01。密碼破譯的關鍵是確定每個密碼的含義。

經過長期統計分析,現在知道了每個密碼的固定長度,如今,我方又截獲了敵方的兩段密文s1和s2,並且知道s1=s2,即兩段密文代表相同的明文。你的任務是幫助情報人員對給定的兩段密文進行分析,看一看有多少種可能的明文。

【輸入檔案】

第1行: s1 (第1段密文)

第2行: s2 (第2段密文)

第3行: n (密碼總數, n<=26)

第4—n+3行: 字母i 長度i (密碼用小寫英文本母表示, 密碼長度<=100)

【輸出檔案】

m(表示有m種可能的明文)

【輸入輸出樣例】

encrypt.in

100ad1

cc14

a 2d 3

c 4b 50

encrypt.out

2【約束條件】

明文的長度<=10000  

注意:如果兩個密文出現矛盾情況,則輸出0。

[size=x-large]【思路】樹狀[color=red]並查集[/color]應用

將需要相等的位置的合併,

統計有ans組,

每種2個情況,

乘法原理

[size=xx-large]var

p:array ['a'..'z']of record b,e,l:longint; c:boolean; end;

f,a1,a2:array [-2..10000] of longint;

s1,s2:ansistring;c:char;

n,i,l,j,x,y,ans,z,temp:longint;

function father(x:longint):longint; begin

if (f[x]=x)or(f[x]=0) then exit(f[x]) else

begin

f[x]:=father(f[x]);

father:=f[x];

end;

end;

procedure ex; begin

write(0); close(input);close(output);halt;

end;

begin

assign(input,'encrypt.in');reset(input);

assign(output,'encrypt.out');rewrite(output);

readln(s1);readln(s2);

readln(n);

for i:=1 to n do readln(c,p[c].l);

for i:=1 to length(s1) do if (s1[i]<>'1')and(s1[i]<>'0') then p[s1[i]].c:=true;

for i:=1 to length(s2) do if (s2[i]<>'1')and(s2[i]<>'0') then p[s2[i]].c:=true;

l:=2;

for c:='a' to 'z' do if p[c].c then

begin

p[c].b:=l;

inc(l,p[c].l);

p[c].e:=l-1;

end;

z:=l-1;

for i:=1 to l do f[i]:=i;

l:=0;

for i:=1 to length(s1) do

case s1[i] of

'1':begin inc(l);a1[l]:=1;end;

'0':begin inc(l);a1[l]:=0;end;

else

begin

for j:=p[s1[i]].b to p[s1[i]].e do

begin

inc(l);

f[j]:=j;

a1[l]:=j;

end;

end;end;

l:=0;

for i:=1 to length(s2) do

case s2[i] of

'1':begin inc(l);a2[l]:=1;if a1[l]=0 then ex; end;

'0':begin inc(l);a2[l]:=0;if a1[l]=1 then ex; end;

else

begin

for j:=p[s2[i]].b to p[s2[i]].e do

begin

inc(l);

f[j]:=j;

a2[l]:=j;

end;

end;end;

for i:=1 to l do

begin

x:=father(a1[i]);y:=father(a2[i]);

if x+y=1 then ex;

if x>y then f[x]:=y else f[y]:=x;

end;

ans:=0;f[1]:=1;

for i:=2 to z do

begin

temp:=father(f[i]);

if (temp<>1)and(temp<>0) then begin inc(ans); f[temp]:=0;end;

end;

writeln(1 shl ans);

close(input);close(output);

end.

並查集 並查集

本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...

並查集入門(普通並查集 帶刪除並查集 關係並查集)

什麼是並查集?通俗易懂的並查集詳解 普通並查集 基礎並查集 例題 題解 how many tables problem description lh boy無聊的時候很喜歡數螞蟻,而且,還給每乙隻小螞蟻編號,通過他長期的觀察和記錄,發現編號為i的螞蟻會和編號為j的螞蟻在一起。現在問題來了,他現在只有...

並查集,帶權並查集

題意 ignatius過生日,客人來到,他想知道他需要準備多少張桌子。然而一張桌子上面只能坐上相互熟悉的人,其中熟悉可定義成為a與b認識,b與c認識,我們就說a,b,c相互熟悉 例如a與b熟悉and b與c熟悉,d與e熟悉,此時至少需要兩張桌子。輸入 t表示樣例個數,n表示朋友個數,朋友從1到n編號...