确定在仅允许插入/删除/替换操作时是否可以将字符串转换为另一个字符串

时间:2010-07-06 16:14:12

标签: java algorithm string

我必须编写一个函数,它将两个单词(字符串)作为参数,并确定是否只使用一个一阶变换将第一个单词转换为第二个单词。

  • 一阶转换只会改变单词中的一个字母

  • 允许的转换是:插入,删除和替换

    • insert =在单词
    • 的任意位置插入一个字母
    • 删除=删除字词
    • 中任意位置的字母
    • replace =用另一个字母替换一个字母

有什么建议吗?任何Java示例都会很棒!

4 个答案:

答案 0 :(得分:5)

想想:如果你只允许进行一次转换,那么“之前”和“之后”之间的长度差异应该会给你一个非常强烈的暗示,即这三个转换中哪一个有成功的机会。出于同样的原因,你可以一眼就看出哪些变换根本不可能。

一旦你决定了哪个转型,问题的其余部分就会成为Brute Force Man和他的搭档Looping Lady的工作。

答案 1 :(得分:2)

这看起来像是家庭作业,所以我不打算给你答案,但是当你接近这样的问题时,最好的办法就是开始草拟一些想法。将问题分解为更小的块,然后变得更容易解决。

例如,让我们看一下插入操作。要插入一个字母,那么我们插入字母的单词的长度是怎么回事?增加还是减少呢?如果我们增加单词的长度,并且这个新单词的长度不等于我们试图匹配的单词的长度,那么它告诉你什么?因此,这里的一个条件是,如果要对第一个单词执行插入操作以使其与第二个单词匹配,则第一个单词必须具有已知长度。

您可以将类似的想法应用于其他两项操作。

因此,一旦建立了这些条件,就可以更容易地开发算法来解决问题。

在这样的任何类型的任务中,重要的是要仔细思考。不要只问别人,“给我代码”,你什么都不会这样。当你遇到困难时,可以寻求帮助(但告诉我们你到目前为止所做的事情),但是家庭作业的目的是学习。

答案 2 :(得分:1)

您可以使用Levenshtein距离并且仅允许距离为1(这意味着必须更改一个char)。有几个实现只是google“Levenshtein java”左右。

另一个“不那么聪明”,但工作的东西将是好老蛮力。只需尝试每个字符的每个情况,你就可以得到你想要的东西。 : - )

答案 3 :(得分:1)

如果您需要检查s1s2是否只有一个编辑,那么通过简单的线性扫描就可以轻松查看。

  • 如果两者具有相同的长度,则必须只有一个索引,其中两者不同
    • 他们必须同意一个共同的最长前缀,然后从两者中只跳过一个字符,然后他们必须就共同的后缀达成一致
  • 如果一个比另一个短,则长度差异必须恰好为1
    • 他们必须同意一个共同的最长前缀,然后从较长的一个字符中跳过一个字符,然后他们必须就一个共同的后缀达成一致

如果您还允许从s1s2进行零修改,只需检查它们是否为equal

这是一个Java实现:

static int firstDifference(String s1, String s2, int L) {
    for (int i = 0; i < L; i++) {
        if (s1.charAt(i) != s2.charAt(i)) {
            return i;
        }
    }
    return L;
}
static boolean oneEdit(String s1, String s2) {
    if (s1.length() > s2.length()) {
        return oneEdit(s2, s1);
    }
    final int L = s1.length();
    final int index = firstDifference(s1, s2, L);
    if (s1.length() == s2.length() && index != L) {
        return s1.substring(index+1).equals(s2.substring(index+1));
    } else if (s2.length() == L + 1) {
        return s1.substring(index).equals(s2.substring(index+1));
    } else {
        return false;
    }
}

然后我们可以按如下方式测试它:

    String[][] tests = {
        { "1", "" },
        { "123", "" },
        { "this", "that" },
        { "tit", "tat" },
        { "word", "sword" },
        { "desert", "dessert" },
        { "lulz", "lul" },
        { "same", "same" },
    };
    for (String[] test : tests) {
        System.out.printf("[%s|%s] = %s%n",
            test[0], test[1], oneEdit(test[0], test[1])
        );
    }

打印(as seen on ideone.com):

[1|] = true
[123|] = false
[this|that] = false
[tit|tat] = true
[word|sword] = true
[desert|dessert] = true
[lulz|lul] = true
[same|same] = false