使用 BFS 的单词梯 2

Word ladder 2 using BFS

本文关键字:单词梯 BFS 使用      更新时间:2023-10-16

海编辑!!下面

我正在编写一个单词梯形图算法。用户输入开始词、结束词和所有单词的哈希。该算法返回从起始字到结束字的所有最短路径(如果存在多个(。例如 -> start_word = "冷" , end_word = "暖">

输出 = [[ 冷 -> 电源线>卡>病房>暖],[/如果存在另一条路径/]]。

前一个单词的每个连续单词都相差一个字符。我正在使用BFS搜索来解决这个问题。我的策略是返回所有路径,然后从返回的列表中选择最短的路径。这是我返回所有路径的代码:

auto word_ladder::generate(std::string const& from, std::string const& to, absl::flat_hash_set<std::string> const& lexicon) -> std::vector<std::vector<std::string>> {

absl::flat_hash_set<std::string> visited = {};
std::queue<std::vector<std::string>> search_queue = {};
std::vector<std::vector<std::string>> paths = {};
search_queue.push(std::vector<std::string>{from});
while (!search_queue.empty()) {
auto word = search_queue.front();
search_queue.pop();
auto neighbours = generate_neighbours(word.back(), lexicon);
for (auto &i: neighbours) {
auto new_word = word;
new_word.push_back(i);
if (i == to) {
paths.push_back(new_word);
continue;
}
if (visited.find(i) != visited.end()) {
continue;
}
search_queue.push(new_word);
visited.insert(i);
}
}
return paths;
}

它确实返回多个路径,但问题是它不会返回所有路径。它返回的路径之一是 ->

1(清醒,觉知,软件,分享,夏尔,希尔,希尔,纯粹,羊,睡眠

但是它不返回路径 -> 2("清醒","感知","软件","共享","sharn","shawn","shewn","sheen","sheep","sleep">

我很确定原因是因为我编码它的方式,它将"共享"一词标记为第一次遇到它时访问过(在 1 中(。因此,它不会通过第二条路径(在 2 中((

为了解决这个问题,我稍微改变了我的 for 循环:

for (auto &i: neighbours) {
auto new_word = word;
new_word.push_back(i);
if (i == to) {
paths.push_back(new_word);
continue;
}
for (auto &j: word) {
if (j == i) {
continue;
}
}
search_queue.push(new_word);
}

这个想法是检查该单词是否已在队列中跟踪的路径中访问过,而不是全局访问过。但是,由于某种原因,此解决方案卡在某个地方的循环中并且不会终止(我假设由于数据集很大?

我的代码在第二个有问题,还是由于数据集大而花费的时间太长?如何更好地实现解决方案?

编辑!!!

我现在不是找到所有路径,而是找到最短路径的长度,然后执行BFS直到该深度以获得该深度的所有路径。

auto word_ladder::generate(std::string const& from, std::string const& to, absl::flat_hash_set<std::string> const& lexicon) -> std::vector<std::vector<std::string>> {

absl::flat_hash_set<std::string> visited = {};
visited.insert(from);
std::queue<std::vector<std::string>> search_queue = {};
std::vector<std::vector<std::string>> paths = {};
search_queue.push(std::vector<std::string>{from});
auto length = find_shortest_path_length(from, to, lexicon);
std::cout << "length is: " << length << "n";
// auto level = 0;
std::unordered_map<std::string, int> level_track = {};
level_track[from] = 0;
while (!search_queue.empty() ) {
auto word = search_queue.front();
search_queue.pop();
// **
if (level_track[word.back()] <= length) {
auto neighbours = generate_neighbours(word.back(), lexicon);
const auto &parent = word.back();
for (auto &i: neighbours) {
auto new_word = word;
new_word.push_back(i);
if (i == to) {
paths.push_back(new_word);
std::cout << "The level at the path was " << level_track[parent] << "n";
continue;
}
if (path_crossed(word, i)) {
continue;
}

search_queue.push(new_word);
level_track[i] = level_track[parent] + 1;
}
}
}
return paths;
}

解决方案现在终止了,所以之前的问题肯定是大量的搜索。但是,我的算法仍然没有给我正确的答案,因为我跟踪节点(单词(深度的方式在某种程度上是不正确的。

您正在尝试找到一个有效的解决方案,但很可能它不存在。看到这个答案。枚举所有最短路径的成本可能非常高。