#include <unordered_set>
#include <string>
#include <vector>
#include <climits>
#include <cstddef>
#include <queue>
namespace word_ladder {
[ [ nodiscard] ] auto generate( std:: string const & from,
std:: string const & to,
std:: unordered_set < std:: string > const & lexicon)
- > std:: vector < std:: vector < std:: string >> {
std:: vector < std:: vector < std:: string >> answer;
std:: unordered_set < std:: string > words;
words.insert ( lexicon.cbegin ( ) , lexicon.cend ( ) ) ;
std:: queue < std:: vector < std:: string >> paths;
paths.push ( { from} ) ;
std:: size_t level = 1 ;
std:: size_t minLevel = INT_MAX ;
std:: unordered_set < std:: string > visited;
while ( ! paths.empty ( ) ) {
std:: vector < std:: string > path = paths.front ( ) ;
paths.pop ( ) ;
if ( path.size ( ) > level) {
for ( std:: string w : visited) {
words.erase ( w) ;
}
visited.clear ( ) ;
if ( path.size ( ) > minLevel) {
break ;
}
else {
level = path.size ( ) ;
}
}
std:: string last = path.back ( ) ;
for ( std:: size_t i = 0 ; i < last.size ( ) ; ++ i) {
std:: string news = last;
for ( char c = 'a' ; c <= 'z' ; ++ c) {
news[ i] = c;
if ( words.find ( news) ! = words.end ( ) ) {
std:: vector < std:: string > newpath = path;
newpath.push_back ( news) ;
visited.insert ( news) ;
if ( news == to) {
minLevel = level;
answer.push_back ( newpath) ;
}
else {
paths.push ( newpath) ;
}
}
}
}
}
return answer;
}
}
I2luY2x1ZGUgPHVub3JkZXJlZF9zZXQ+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxjbGltaXRzPgojaW5jbHVkZSA8Y3N0ZGRlZj4KI2luY2x1ZGUgPHF1ZXVlPgoKCm5hbWVzcGFjZSB3b3JkX2xhZGRlciB7CgoJW1tub2Rpc2NhcmRdXSBhdXRvIGdlbmVyYXRlKHN0ZDo6c3RyaW5nIGNvbnN0ICYgZnJvbSwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGQ6OnN0cmluZyBjb25zdCAmIHRvLAoJICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6dW5vcmRlcmVkX3NldDxzdGQ6OnN0cmluZz4gY29uc3QgJiBsZXhpY29uKQoJICAgLT4gc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+PiB7CgkJc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+PiBhbnN3ZXI7CgoJCXN0ZDo6dW5vcmRlcmVkX3NldDxzdGQ6OnN0cmluZz4gd29yZHM7CgkJd29yZHMuaW5zZXJ0KGxleGljb24uY2JlZ2luKCksIGxleGljb24uY2VuZCgpKTsKCgkJc3RkOjpxdWV1ZTxzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4+IHBhdGhzOwoJCXBhdGhzLnB1c2goe2Zyb219KTsKCgkJc3RkOjpzaXplX3QgbGV2ZWwgPSAxOwoJCXN0ZDo6c2l6ZV90IG1pbkxldmVsID0gSU5UX01BWDsKCgkJc3RkOjp1bm9yZGVyZWRfc2V0PHN0ZDo6c3RyaW5nPiB2aXNpdGVkOwoKCQl3aGlsZSAoIXBhdGhzLmVtcHR5KCkpIHsKCQkJc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IHBhdGggPSBwYXRocy5mcm9udCgpOwoJCQlwYXRocy5wb3AoKTsKCQkJaWYgKHBhdGguc2l6ZSgpID4gbGV2ZWwpIHsKCQkJCWZvciAoc3RkOjpzdHJpbmcgdyA6IHZpc2l0ZWQpIHsKCQkJCQl3b3Jkcy5lcmFzZSh3KTsKCQkJCX0KCQkJCXZpc2l0ZWQuY2xlYXIoKTsKCQkJCWlmIChwYXRoLnNpemUoKSA+IG1pbkxldmVsKSB7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlsZXZlbCA9IHBhdGguc2l6ZSgpOwoJCQkJfQoJCQl9CgoJCQlzdGQ6OnN0cmluZyBsYXN0ID0gcGF0aC5iYWNrKCk7CgkJCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBsYXN0LnNpemUoKTsgKytpKSB7CgkJCQlzdGQ6OnN0cmluZyBuZXdzID0gbGFzdDsKCQkJCWZvciAoY2hhciBjID0gJ2EnOyBjIDw9ICd6JzsgKytjKSB7CgkJCQkJbmV3c1tpXSA9IGM7CgkJCQkJaWYgKHdvcmRzLmZpbmQobmV3cykgIT0gd29yZHMuZW5kKCkpIHsKCQkJCQkJc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IG5ld3BhdGggPSBwYXRoOwoJCQkJCQluZXdwYXRoLnB1c2hfYmFjayhuZXdzKTsKCQkJCQkJdmlzaXRlZC5pbnNlcnQobmV3cyk7CgkJCQkJCWlmIChuZXdzID09IHRvKSB7CgkJCQkJCQltaW5MZXZlbCA9IGxldmVsOwoJCQkJCQkJYW5zd2VyLnB1c2hfYmFjayhuZXdwYXRoKTsKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCXBhdGhzLnB1c2gobmV3cGF0aCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJcmV0dXJuIGFuc3dlcjsKCX0KCn0=