#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
#include <iostream>
std::size_t levenshtein_distance( std::string first, std::string second )
{
if( second.size() < first.size() ) std::swap(first,second) ;
std::vector<std::size_t> current( second.size()+1 ), previous(current) ;
std::iota( previous.begin(), previous.end(), 0 ) ;
for( std::size_t i = 0 ; i < first.size() ; ++i )
{
current[0] = i+1 ;
for( std::size_t j = 0 ; j < second.size() ; ++j )
{
current[j+1] = std::min( std::min( current[j], previous[j+1]) + 1,
previous[j] + ( first[i] != second[j] ) ) ;
}
current.swap(previous);
}
return previous.back() ;
}
std::vector<std::string> nearest_words( const std::string& word, const std::vector<std::string>& dict )
{
constexpr std::size_t MAX_DISTANCE = 5 ;
std::vector<std::string> nearest[MAX_DISTANCE+1] ;
for( const std::string match : dict )
{
std::size_t dist = levenshtein_distance( word, match ) ;
if( dist <= MAX_DISTANCE ) nearest[dist].push_back(match) ;
}
for( const auto& seq : nearest ) if( !seq.empty() ) return std::move(seq) ;
return {} ;
}
int main()
{
const std::vector<std::string>& dict { "mess", "less", "plus", "pious", "messes", "misses", "lessen", "listen" } ;
const std::string test[] = { "mises", "missse", "mesten", "pius" } ;
for( const std::string& word : test )
{
std::cout << word << " => " ;
for( const auto& nearest : nearest_words( word, dict ) ) std::cout << nearest << ' ' ;
std::cout << '\n' ;
}
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPG51bWVyaWM+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnN0ZDo6c2l6ZV90IGxldmVuc2h0ZWluX2Rpc3RhbmNlKCBzdGQ6OnN0cmluZyBmaXJzdCwgc3RkOjpzdHJpbmcgc2Vjb25kICkKewogICAgaWYoIHNlY29uZC5zaXplKCkgPCBmaXJzdC5zaXplKCkgKSBzdGQ6OnN3YXAoZmlyc3Qsc2Vjb25kKSA7CiAgICBzdGQ6OnZlY3RvcjxzdGQ6OnNpemVfdD4gY3VycmVudCggc2Vjb25kLnNpemUoKSsxICksIHByZXZpb3VzKGN1cnJlbnQpIDsKICAgIHN0ZDo6aW90YSggcHJldmlvdXMuYmVnaW4oKSwgcHJldmlvdXMuZW5kKCksIDAgKSA7CgogICAgZm9yKCBzdGQ6OnNpemVfdCBpID0gMCA7IGkgPCBmaXJzdC5zaXplKCkgOyArK2kgKQogICAgewogICAgICAgIGN1cnJlbnRbMF0gPSBpKzEgOwogICAgICAgIGZvciggc3RkOjpzaXplX3QgaiA9IDAgOyBqIDwgc2Vjb25kLnNpemUoKSA7ICsraiApCiAgICAgICAgewogICAgICAgICAgICBjdXJyZW50W2orMV0gPSBzdGQ6Om1pbiggc3RkOjptaW4oIGN1cnJlbnRbal0sIHByZXZpb3VzW2orMV0pICsgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzW2pdICsgKCBmaXJzdFtpXSAhPSBzZWNvbmRbal0gKSApIDsKICAgICAgICB9CiAgICAgICAgY3VycmVudC5zd2FwKHByZXZpb3VzKTsKICAgIH0KICAgIHJldHVybiBwcmV2aW91cy5iYWNrKCkgOwp9CgpzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4gbmVhcmVzdF93b3JkcyggY29uc3Qgc3RkOjpzdHJpbmcmIHdvcmQsIGNvbnN0IHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiYgZGljdCApCnsKICAgIGNvbnN0ZXhwciBzdGQ6OnNpemVfdCBNQVhfRElTVEFOQ0UgPSA1IDsKICAgIHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiBuZWFyZXN0W01BWF9ESVNUQU5DRSsxXSA7CiAgICBmb3IoIGNvbnN0IHN0ZDo6c3RyaW5nIG1hdGNoIDogZGljdCApCiAgICB7CiAgICAgICAgc3RkOjpzaXplX3QgZGlzdCA9IGxldmVuc2h0ZWluX2Rpc3RhbmNlKCB3b3JkLCBtYXRjaCApIDsKICAgICAgICBpZiggZGlzdCA8PSBNQVhfRElTVEFOQ0UgKSBuZWFyZXN0W2Rpc3RdLnB1c2hfYmFjayhtYXRjaCkgOwogICAgfQoKICAgIGZvciggY29uc3QgYXV0byYgc2VxIDogbmVhcmVzdCApIGlmKCAhc2VxLmVtcHR5KCkgKSByZXR1cm4gc3RkOjptb3ZlKHNlcSkgOwogICAgcmV0dXJuIHt9IDsKfQoKaW50IG1haW4oKQp7CiAgICBjb25zdCBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIGRpY3QgeyAibWVzcyIsICJsZXNzIiwgInBsdXMiLCAicGlvdXMiLCAibWVzc2VzIiwgIm1pc3NlcyIsICJsZXNzZW4iLCAibGlzdGVuIiB9IDsKICAgIGNvbnN0IHN0ZDo6c3RyaW5nIHRlc3RbXSA9IHsgIm1pc2VzIiwgIm1pc3NzZSIsICJtZXN0ZW4iLCAicGl1cyIgfSA7CiAgICBmb3IoIGNvbnN0IHN0ZDo6c3RyaW5nJiB3b3JkIDogdGVzdCApCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHdvcmQgPDwgIiA9PiAiIDsKICAgICAgICBmb3IoIGNvbnN0IGF1dG8mIG5lYXJlc3QgOiBuZWFyZXN0X3dvcmRzKCB3b3JkLCBkaWN0ICkgKSBzdGQ6OmNvdXQgPDwgbmVhcmVzdCA8PCAnICcgOwogICAgICAgIHN0ZDo6Y291dCA8PCAnXG4nIDsKICAgIH0KfQo=