1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
#include <fstream>
#include <iostream>
#include "trie.hpp"

struct Key
{
    static constexpr size_t
    size()
    {
        return ('Z' - 'A' + 1);
    }

    static constexpr size_t
    map(char c)
    {
        assert(c>='a' && c<='z' || c>='A' && c<='Z');
        if (c>='a' && c<='z') {
            c = c'a' + 'A';
        }
        return c'A';
    }

    static constexpr char
    unmap(size_t key)
    {
        assert(key<size());
        return 'a' + key;
    }
};

bool
is_word(const std::string& word)
{
    for (char ch: word) {
        if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) {
            return false;
        }
    }
    return true;
}


void
longest_path(Trie<std::string, Key>::Pointer p, unsigned int count,
             unsigned int& maxcount, Trie<std::string, Key>::Pointer& maxseen)
{
    if (!p.defined()) return;
    if (p.exists()) {
        ++count;
        if (count > maxcount) {
            maxcount = count; maxseen = p;
        }
    }
    for (char ch: p) {
        auto ptr = p;
        ptr.descend(ch);
        longest_path(ptr, count, maxcount, maxseen);
    }
}

int
main()
{
    //std::ifstream words("/usr/dict/words");
    std::ifstream words("words");
    if (!words) {
        std::cerr << "Can not open /usr/dict/words" << std::endl;
    }

    Trie<std::string, Key>  trie;
    std::string             line;
    while (std::getline(words, line)) {
        if (is_word(line)) {
            trie.insert(line, line);
        }
    }

    std::string key;
    while (std::cin >> key) {
        if (is_word(key)) {
            auto ptr = trie.descend();
            if (ptr.defined()) {
                for (char ch: key) {
                    if (!ptr.descend(ch)) break;
                    if (ptr.exists()) {
                        std::cout << *ptr << std::endl;
                    }
                }
                if (ptr.defined()) {
                    std::cout << "continuation possible with: ";
                    for (char ch: ptr) {
                        std::cout << ch;
                    }
                    std::cout << std::endl;
                }
            }
        }
    }
    Trie<std::string, Key>::Pointer maxpath;
    unsigned int maxcount = 0;
    longest_path(trie.descend(), 0, maxcount, maxpath);
    if (maxcount0) {
        std::cout << *maxpath << std::endl;
    }
}