当前位置: 首页 > 知识库问答 >
问题:

找到两个给定单词和一本词典之间的最短单词阶梯

禹正阳
2023-03-14

我试图从字典中找到两个给定单词之间的最短梯子。所有单词,包括给定的单词和字典中的单词都具有相同的字符数。在一次传递中,只能更改一个字符,并且需要最短路径。例如:给定:“命中”和“cil” Dic:[“hil”,“hol”,“hot”,“lot”,“lit”,“lil”] 所以,答案应该是“命中”-

我已经尝试使用BFS解决这个问题;通过在字典中找到下一个单词并检查它是否与队列中弹出的项目相邻。不过,这种方法不会给我最短路径:

如果,我试图用26个字母替换每个字母,并且如果字典中出现了生成的单词,请接受这一点:这种方法仍然不会给我最短的路径。例:这里,它会给我:一击-

也许,更好的方法是先构造一棵树,然后在树中找到从起始单词到结束单词的最短路径。

我知道,这个论坛上有这个问题的解决方案,但没有一个解释算法。我是BFS的新手,所以不太熟悉。我有兴趣知道如何找到最短路径之一,如果有几个,那么所有最短路径。

共有3个答案

南门朗
2023-03-14

我通过采用以下方法找到了一个解决方案:1)我首先从字典中建立了一棵树,假设起点是给定的单词;然后,我尝试使用这棵树构建从给定单词到结束单词的所有可能路径。

复杂度:O(n*70 2^n-1 * lg(n)) = O(2^n-1*lg(n)) 这里 n 是字典中的单词数,70 是 ASCII 值的范围,从 65 到 122(A 到 a),我在这里取了一个整数。正如预期的那样,复杂性呈指数级增长。即使经过某些优化,最坏情况的复杂性也不会改变。

这是我写的代码(它由我测试并有效。任何错误或建议将不胜感激。

#include <iostream>
#include <vector>
#include <cstring>
#include <deque>
#include <stack>
#include <algorithm>

using namespace std;

struct node {
    string str;
    vector<node *> children;
    node(string s) {
        str = s;
        children.clear();
    }
};

bool isAdjacent(string s1, string s2) {
    int table1[70], table2 [70];
    int ct = 0;

    for (int i = 0; i < 70; i++) {
        table1[i] = 0;
        table2[i] = 0;
    }
    for (int i = 0; i < s1.length(); i++) {
        table1[((int)s1[i])- 65] += 1;
        table2[((int)s2[i])- 65] += 1;
     }

     for (int i = 0; i < 70; i++) {
        if (table1[i] != table2[i])
            ct++;
        if (ct > 2)
            return false;
     }
     if (ct == 2)
        return true;
     else
        return false;
}

void construct_tree(node *root, vector<string> dict) {
    deque<node *> q;
    q.push_back(root);
    while (!q.empty()) {
        node *curr = q.front();
        q.pop_front();
        if (dict.size() == 0)
            return;
        for (int i = 0; i < dict.size(); i++) {
            if (isAdjacent(dict[i], curr->str)) {
                string n = dict[i];
                dict.erase(dict.begin()+i);
                i--;
                node *nnode = new node(n);
                q.push_back(nnode);
                curr->children.push_back(nnode);
            }
        }
    }
}

void construct_ladders(stack<node *> st, string e, vector<vector <string> > &ladders) {
    node *top = st.top();
    if (isAdjacent(top->str,e)) {
        stack<node *> t = st;
        vector<string> n;
        while (!t.empty()) {
            n.push_back(t.top()->str);
            t.pop();
        }
        ladders.push_back(n);
    }
    for (int i = 0; i < top->children.size(); i++) {
        st.push(top->children[i]);
        construct_ladders(st,e,ladders);
        st.pop();
    }
}

void print(string s, string e, vector<vector<string> > ladders) {
    for (int i = 0; i < ladders.size(); i++) {
        for (int j = ladders[i].size()-1; j >= 0; j--) {
            cout<<ladders[i][j]<<" ";
        }
        cout<<e<<endl;
    }
}

int main() {
    vector<string> dict;
    string s = "hit";
    string e = "cog";

    dict.push_back("hot");
    dict.push_back("dot");
    dict.push_back("dog");
    dict.push_back("lot");
    dict.push_back("log");

    node *root = new node(s);
    stack<node *> st;
    st.push(root);

    construct_tree(root, dict);

    vector<vector<string> > ladders;
    construct_ladders(st, e, ladders);

    print(s,e,ladders);

    return 0;
}
闾丘谦
2023-03-14

这种方法有点蛮力,但可能是一个很好的起点。

如果目标单词等于起始单词,或者距离为1,则结果为< code>[start,target],这样就完成了。

否则,您必须查找词典中与起始单词距离为1的所有成员。如果其中一个单词与目标单词的距离为1,那么结果是[start,word,target],就完成了。否则,您将以所选列表中的每个单词作为开始,以目标作为目标,并将start前置到最短的结果。

伪代码 - 有点像python:

myDict = {"hil", "hol", "hot", "lot", "lit", "lil"}

used_wordlist = {}

shortestWordLadder(start, target):
    if start == target or levenshtein(start, target) = 1:
        return [start, target]

    current_wordlist = [x for x in myDict
                              if x not in used_wordlist and
                              levenshtein(ladder[-1], x) = 1]

    if current_wordlist.size = 0:
        return null

    for word in current_wordlist:
        if levenshtein(word, target) == 1:
            return [start, word, target]

     used_wordlist.insert_all(current_wordlist)
     min_ladder_size = MAX_INT
     min_ladder = null

     for word in currrent_wordlist:
         ladder = shortestWordLadder(word, target)

         if ladder is not null and ladder.size < min_ladder_size:
             min_ladder_size = ladder.size
             min_ladder = ladder.prepend(start)

     return min_ladder

可能的优化:

我考虑重用矩阵,levenshtein(start, Target)将在内部创建,但我无法获得足够的信心,它可以在所有情况下工作。这个想法是从矩阵的右下角开始,选择最小的邻居,这将从字典中创建一个单词。然后继续这个位置。如果当前单元格的邻居没有从字典中创建一个单词,我们必须回溯,直到找到一个值为0的字段。如果回溯将我们带回右下角单元格,则没有解决方案。

我现在不确定,可能没有解决方案,你可能会忽略这种方式。如果它找到解决方案,我很有信心,它是最短的之一。

目前我没有时间考虑清楚。如果证明这不是一个完整的解决方案,您可以将它用作一个优化步骤,而不是< code > shortestworldladder()的第一行中的< code>levenshtein(start,target)调用,因为该算法会为您提供levenshtein距离,如果可能的话,还会提供最短路径。

卜泓
2023-03-14

我建议在字典中的单词上构建一个图,其中一个节点表示一个单词

 类似资料:
  • 给定两个文件会产生一个算法/程序来查找文件1中的单词,而不是文件2中的单词。请注意,文件中的单词不是按顺序排列的。 这是我的思考过程: 步骤1:读取文件2的单词并将其添加到哈希集 如果两个文件中的字数都只有100或1000个,那么这个算法就可以正常工作 但是,如果两个文件都很大(数十亿字),那么此解决方案将无法工作,因此我提出了一个改进的解决方案: 步骤1:逐字阅读文件2,并按字母顺序对单词进行排

  • 问题内容: 如何提取Linux(csh)中特定单词之后的单词?更确切地说,我有一个文件,其中只有一行看起来像这样: 我想提取单词 后面的数字。我不能使用sed,因为仅当您要提取整行时才可以使用sed。也许我可以使用awk? 另外,我有多个具有不同值的文件,所以我需要一些提取值但不依赖于值的文件。 问题答案: 与: 基本上循环遍历该行的每个单词。当您找到要查找的第一个单词时,抓住下一个单词并打印出来

  • 所以我做了一个函数 因此,它所做的是获取一个字符串,将其拆分,并生成一个字典,其中键是单词,值是它出现的次数。 好的,我现在要做的是,做一个函数,它接受这个函数的输出,并产生一个如下格式的列表- ((超过1个字母的单词列表),(最常用单词列表),(最长单词列表)) 另外,例如,假设两个单词出现了3次,并且两个单词都有6个字母长,那么这两个单词都应该包含在(最频繁的)和(最长的)列表中。 因此,到目

  • 问题内容: 我有一个嘈杂的数据。 现在我只想提取。有没有办法删除这两个定界符和之间的文本? 问题答案: 使用正则表达式: [更新] 如果您尝试过类似的模式,其中的点表示任何字符,而加号表示一个或多个,则您知道它不起作用。 为什么!?!这是因为正则表达式默认情况下是“贪婪的”。该表达式将匹配字符串之前的所有内容,包括-,这不是我们想要的。我们要匹配并在下一个处停止,因此我们使用的模式表示“除x外的任

  • 问题内容: 我需要在两列之间匹配一些单词。我无法在任何地方找到此解决方案,因此我需要帮助。 输出==> 如何比较表中名为“ title”的这两列,我需要在两列之间匹配一些单词。例如,在第1行中,“ Toscano”在两列中都是通用的,在第2行中,“奶油蛋卷”是通用的。 问题答案: 也许是这样的(这里是SQL FIDDLE )?

  • 我在寻找单词“house”和“car”时有一个要求,但它们必须在10个单词之间。我有以下正则表达式: 这适用于任何单词组合。但是,这并不满足“10字以内”的要求: 因此,以下内容将是一个很好的匹配: 但是,以下内容不应匹配: 汽车文字1文字2文字3文字4文字5文字6文字7文字8文字9文字10文字11房屋 我怎样才能做到这一点?提前感谢。

  • 问题内容: 我在这里浏览了一些问题,但这些问题似乎都不是我的问题。假设我有2个字典,它们是dict1 和字典2 我正在编写一个程序,需要将它们结合到一个字典finaldict中 非常感谢您的帮助,我一直在努力,现在已经一无所获 问题答案: 这是通用版本。即使只有键之一存在键,也可以用它来创建一个以值作为列表的字典。 输出量 如果您使用的是Python 2,则必须像这样更改for循环:

  • 我最初在这里发布了这个问题,但后来被告知将其发布到代码审查;然而,他们告诉我,我的问题需要在这里发布。我会试着更好地解释我的问题,希望没有混淆。我正在尝试编写一个单词一致性程序,它将执行以下操作: 1) 读“停”字。txt文件放入一个只包含停止词的字典(使用与您计时的字典类型相同的字典),称为stopWordDict。(警告:在将换行符('\n')添加到stopWordDict之前,请先将其从停止