#include #include #include #define MAX 256 #define INFTY 10000 // Nekonečno struct vrchol { // Vrchol trie struct vrchol *syn[2]; // syn[0] pro tečku, syn[1] pro čárku struct slovo *slova; // Seznam slov, která tu končí int hloubka; // Délka morseovkového zápisu (hloubka v trii) }; struct vrchol koren; struct slovo { // Takhle si ukládáme seznamy slov struct slovo *dalsi; // Vlastně by si stačilo pamatovat jen jedno slovo, char s[1]; // ale třeba se to bude hodit v následující úloze :) }; // Tabulka kódů: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z char morse[26] = { 6,17,21, 9, 2,20,11,16, 4,30,13,18, 7, 5,15,22,27,10, 8, 3,12,24,14,25,29,19 }; void preloz(char *co, char *kam) // Přeloží slovo do morseovky { while (*co) { int k = morse[*co++ - 'a']; // Ďábelský kód písmenka while (k > 1) { // Postupně rozkládáme na značky *kam++ = ".-"[k%2]; k /= 2; } } *kam = 0; } void nacti_slovnik(void) { char slovo[MAX], mslovo[MAX]; while (fgets(slovo, sizeof(slovo), stdin) && slovo[0] != '\n') { int len = strlen(slovo); slovo[len-1] = 0; // Smažeme konec řádku preloz(slovo, mslovo); // Přeložíme do morseovky struct vrchol *v = &koren; // Přidáváme do trie for (char *c=mslovo; *c; c++) { int z = (*c == '-'); // Aktuální značka if (!v->syn[z]) { // Kam dál? Není-li kam, založíme nový vrchol v->syn[z] = malloc(sizeof(struct vrchol)); memset(v->syn[z], 0, sizeof(struct vrchol)); v->syn[z]->hloubka = v->hloubka + 1; } v = v->syn[z]; // Vydáme se tím směrem } struct slovo *s = malloc(sizeof(struct slovo) + len); // Stojíme ve vrcholu, který odpovídá konci slova, s->dalsi = v->slova; // tak tam slovo přidáme v->slova = s; strcpy(s->s, slovo); } } int main(void) { char z[MAX]; // Vstupní řetězec int n; // Jeho délka int b[MAX+1]; // Viz popis řešení struct vrchol *s[MAX+1]; nacti_slovnik(); // Přečteme slovník a vstup fgets(z+1, MAX, stdin); // Pozor, indexujeme od 1 n = strlen(z+1)-1; b[n+1] = 0, s[n+1] = NULL; // Spočítáme všechna b[i] a s[i] for (int i=n; i; i--) { b[i] = INFTY, s[i] = NULL; struct vrchol *v = &koren; // Hledáme pasující slova int j = i; while (v && j <= n) { int zn = (z[j++] == '-'); // Následující značka v = v->syn[zn]; // Poskočíme v trii if (v && v->slova && b[j] < b[i]) // Sem nějaké slovo pasuje b[i] = b[j]+1, s[i] = v; } } if (b[1] >= INFTY) // Pokud řešení existuje, tak ho vypíšeme puts("Řešení neexistuje"); else { printf("Našli jsme řešení na %d slova:\n", b[1]); int i = 1; while (i <= n) { puts(s[i]->slova->s); i += s[i]->hloubka; } } return 0; }