【问题标题】:substitution cypher with a dictionary用字典替换密码
【发布时间】:2012-01-29 20:17:45
【问题描述】:

我的家庭作业是根据已知的有限字典来破译一个句子。

示例: 字典 - 显示,吹,同时

然后输入代码 12345 8291。 如果我们要检查可能性,唯一的选择是“同时显示”。

谁能给我一个处理这个问题的方向或已知算法。 伪代码或java会很棒。

谢谢

【问题讨论】:

    标签: algorithm substitution encryption


    【解决方案1】:

    您需要实施某种回溯或其他搜索技术。我建议采用以下方法:

    1. 创建密码到字符转换表。最初,每个密码(数字)映射到 0(无)。
    2. 处理输入。每次遇到未分配的密码数字时,您都可以根据字典和迄今为止确定的字母选择字母。如果没有可分配的字母,则回溯(或以任何对您的搜索技术有意义的方式报告失败)。将每个选项添加到您的搜索控制逻辑。 (例如,如果您使用回溯,请保存选择列表并在翻译表中记录任意选择。如果您回溯到该点,请指定另一个选择。)
    3. 继续前进,直到您到达终点,或者您别无选择。

    编辑:在第 2 步中,困难的部分是确定哪些字母(如果有)可以分配给下一个密码数字。假设我们正在跟踪解码的当前单词,并且我们想要处理单词中的下一个密码数字。我们已经制定了密码数字分配的全球地图。逻辑可能是这样的(在 Java-ish 伪代码中):

    Set assignableLetters(String wordSoFar, int nextCipher) {
        Character assignment = map.get(nextCipher);
        Set set = new Set();
        if (assignment != null) {
            // The next cipher is already assigned. Add the assignment to the
            // return set only if it is compatible with the dictionary contents
            if (dictionary.hasWordsWithPrefix(wordSoFar + assignment)) {
                set.add(assignment);
            }
        } else {
            // The next cipher is not assigned. We will return a set of all
            // compatible characters that can be assigned to it.
            for (Character c : unassignedCharacters()) {
                if (dictionary.hasWordsWithPrefix(wordSoFar + c)) {
                    set.add(c);
                }
            }
        }
        return set;
    }
    

    如果这返回一个空集,则当前分配(在调用方法之前)与字典不兼容,搜索必须回溯。否则,搜索应该从集合中一次选择一个分配并继续,必要时回溯。

    与其尝试每个未分配的字符并询问字典是否兼容,不如直接在字典中查询兼容的下一个字符列表并将其与未分配的字符集相交可能更有效(但在逻辑上等效)。

    【讨论】:

    • 它如何考虑我们在字典中的单词?
    • @user1176889 这将确定新密码数字可能分配的字母(如果有)。分配必须与字典和到目前为止阅读的内容一致。此外,如果已经分配了下一个密码,则必须查阅字典以确定下一个字母是否会出现。 (我在回答中忽略了最后一点。)
    • 感谢您的回答。能不能给个更详细的解释?
    • @user1176889 您想要了解更多详细信息:一般回溯还是后继代?
    • @user1176889 我添加了一些伪代码,展示了一种生成后继的方法