program OrezZarodku; const MaxN = 1000; Open = true; Close = false; {otevřená a zavřená závorka} var t:array[1..2, 1..MaxN * 2] of boolean; {reprezentace 2 stromů, max 2N závorek} tlen : array[1..2] of Integer; {délky reprezentací} procedure ReadTree(tIndex: Integer); var n: Integer; {vrcholů} indices: array[1..MaxN+1] of integer; {začátky seznamů v edge} edge: array[1..MaxN] of integer; {seznam hran} v: Integer; {vrchol} index: Integer; stackE, stackV : array[1..MaxN] of integer; {zásobník hran a vrcholů} stackDepth : Integer; {hloubka zásobníku} begin {načteme seznamy potomků} write('Vrcholů: '); readln(n); index := 1; for v:= 1 to n do begin write(v,': '); indices[v] := index; while not eoln do begin read(edge[index]); index := index + 1; end; readln; end; indices[n+1] := index; {pomocí zásobníku převedeme na závorkovou reprezentaci} stackDepth := 1; {na počátku je v zásboníku jeden vrchol} stackV[1] := 1; {je to kořen = 1} stackE[1] := 1; {a máme se vydat jeho prvním potomkem} t[tIndex, 1] := Open; {zapíšeme si za něj otevírací závorku} index := 2; {další závorky píšeme od pozice 2} while stackDepth > 0 do begin v := stackV[stackDepth]; {vrchol na vrcholu zásobníku :-) } if stackE[stackDepth] <= indices[v + 1] - indices[v] then begin {ještě jsme neprošli nějakou hranu z vrcholu} t[tIndex, index] := Open; {zapíšeme otevírací závorku} index := index + 1; stackV[stackDepth + 1] := edge[indices[v] + stackE[stackDepth] - 1]; stackE[stackDepth + 1] := 1; {nový vrchol má zpracovat prvního syna} stackE[stackDepth] := stackE[stackDepth] + 1; {další hrana hotová} stackDepth := stackDepth + 1; end else begin {opouštíme vrchol} t[tIndex, index] := Close; index := index + 1; stackDepth := stackDepth - 1; end; end; tlen[tIndex] := n * 2; {délka reprezentace} end; var A, B: Integer; KMP : array[1..2 * MaxN] of integer; i, j : Integer; begin ReadTree(1); ReadTree(2); if tlen[1] >= tlen[2] then begin {vetší strom bude rodič} A := 1; B := 2; end else begin A := 2; B := 1; end; {ořízneme vnější pár závorek (jde to bez toho, ale didaktické účely...)} for i := 2 to tlen[B] - 1 do KMP[i - 1] := KMP[i]; tlen[B] := tlen[B] - 2; if tlen[B] = 0 then begin {Ha, test case!} writeln('Strom ', B,' je výsledkem ořezu stromu ', A,'.'); exit; end; {Příprava KMP <- hledáme strom B, stavíme záchranou funkci} KMP[1] := 0; for i := 2 to tlen[B] do if t[B, i] = t[B, KMP[i - 1] + 1] then KMP[i] := KMP[i - 1] + 1 else KMP[i] := 0; {Hledani, j = pozice v B, i = pozice v A} j := 0; for i := 2 to tlen[A] - 1 do {první a poslední závorku lze vynechat} if t[A, i] = t[B, j + 1] then begin j := j + 1; if j = tlen[B] then begin writeln('Strom ', B,' je výsledkem ořezu stromu ', A,'.'); exit; end; end else while (j > 0) and (t[A, i] <> t[B, j + 1]) do j := KMP[j]; {sem se dostane, jen když B v A nenajdeme} writeln('Nejedna se o předka a potomka ve smyslu ořezávání.'); end.