Algorithms-UCSanDiego

Data Structures and Algorithms by UCSanDiego

View project on GitHub

2. Trie Pattern Matching

Problem

Solutions

CPP

#include <iostream>
#include <sstream>
#include <unordered_map>
#include <memory>
#include <queue>
#include <set>
#include <iterator>
#include <algorithm>

using namespace std;
using Positions = set< int >;

class Trie {
public:
    Trie() : N{ 0 }, root{ next() } {}
    void add( const string& s ){
        auto cur{ root };
        for( auto c: s ){
            auto it = cur->children.find( c );
            if( it != cur->children.end() )
                cur = it->second;
            else
                cur = cur->children[ c ] = next();
        }
        cur->children[ '$' ] = next();
    }
    Positions find( const string& s, Positions P={} ) const {
        auto N = s.size();
        for( auto i{ 0 }; i < N; ++i ){
            auto cur{ root };
            for( auto j{ i }; j < N; ++j ){
                auto c = s[ j ];
                auto it = cur->children.find( c );
                if( it != cur->children.end() )
                    cur = it->second;
                else
                    break;
            }
            if( cur->children.find( '$' ) != cur->children.end() )
                P.insert( i );
        }
        return P;
    }
private:
    mutable int N;
    struct Node;
    using HNode = shared_ptr< Node >;
    HNode root;
    struct Node {
        explicit Node( int id_ ) : id{ id_ } {}
        const int id{ 0 };
        using Children = unordered_map< char, HNode >;
        Children children;
    };
    HNode next() const {
        return make_shared< Node >( N++ );
    }
};

int main() {
    string text; cin >> text;
    auto N{ 0 }; cin >> N;
    Trie T; for( string s; N-- && cin >> s; T.add( s ) );
    auto P = T.find( text );
    copy( P.begin(), P.end(), ostream_iterator< int >( cout, " " ) );
    return 0;
}