#!/usr/bin/python #vim: fileencoding=utf-8 from __future__ import division, print_function # Kompatibilita s Py2.x import sys slova = [] for slovo in sys.stdin: slova.append(slovo.strip()) def pridej_hranu(u, v): global pocet_hran cislo_hrany = pocet_hran pocet_hran += 1 sousede[u].append((cislo_hrany, v)) sousede[v].append((cislo_hrany, u)) def vrchol_volny(u): for hrana, soused in sousede[u]: if parovani[hrana]: return False return True # Jednoduché DFS, které chodí střídavě po nepárovacích a párovacích # hranách (a hledá tedy (volné) střídavé cesty). # # Po nalezení zlepšující cesty při návratu z rekurze rovnou zlepšíme # párování. def zlepsujici_cesta_z(u, po_parovaci=False): global znacky if znacky[u]: return False znacky[u] = True for hrana, soused in sousede[u]: # Po párovací hraně jdeme *právě tehdy*, když `po_parovaci' je True # (v lichých vrstvách rekurze). if parovani[hrana] == po_parovaci: if vrchol_volny(soused): # Došli jsme do volného vrcholu, máme zlepšující cestu! parovani[hrana] = True return True else: if zlepsujici_cesta_z(soused, not po_parovaci): # Vracíme se po nalezené zlepšující cestě a invertujeme stav hran. parovani[hrana] = not parovani[hrana] return True return False # Hledej zlepšující cestu ze všech volných vrcholů slovní parity. # Skonči po prvním nálezu. def zlepsujici_cesta(): global znacky znacky = [False] * len(sousede) for u in range(len(hromadka)): if vrchol_volny(u): if zlepsujici_cesta_z(u): return True return False for prvni_pismeno in range(256): hromadka = [] for slovo in slova: if ord(slovo[0]) == prvni_pismeno: hromadka.append(slovo[1:]) # Číslování vrcholů: # 0 až (len(hromadka) - 1) . . . . . . . slova # len(hromadka) až (len(hromadka) + 256*256 - 1) . . zkratky # # Každý prvek dvojice ve tvaru (číslo hrany, druhý konec). # Číslo hrany je potřebné, abychom si mohli udržovat, které # hrany jsou aktuálně v párování. sousede = [ [] for i in range(len(hromadka) + 256*256) ] pocet_hran = 0 for i in range(len(hromadka)): slovo = hromadka[i] # První a poslední výskyt libovolného znaku ve slově prvni_vyskyt = [-1] * 256 posledni_vyskyt = [-1] * 256 for j in range(len(slovo)): znak = ord(slovo[j]) if prvni_vyskyt[znak] == -1: prvni_vyskyt[znak] = j posledni_vyskyt[znak] = j for a in range(256): for b in range(256): # Jde vytvořit zkratka `ab' ze slova `slovo'? if (prvni_vyskyt[a] != -1 and posledni_vyskyt[b] != -1 and prvni_vyskyt[a] < posledni_vyskyt[b]): zkratka = chr(a) + chr(b) pridej_hranu(i, len(hromadka) + 256*a + b) # Udává pro každou hranu, jestli je součástí aktuálního párování parovani = [False] * pocet_hran while zlepsujici_cesta(): pass for i in range(len(hromadka)): for hrana, soused in sousede[i]: if parovani[hrana]: cislo_zkratky = soused - len(hromadka) zkratka = chr(cislo_zkratky // 256) + chr(cislo_zkratky % 256) print("%-15s %s" % (chr(prvni_pismeno) + hromadka[i], chr(prvni_pismeno) + zkratka))