【问题标题】:How to convert a string to a palindrome with minimum number of character replacement such that palindromic string contains a given word?如何将字符串转换为具有最少字符替换次数的回文,以使回文字符串包含给定的单词?
【发布时间】:2017-03-19 03:32:07
【问题描述】:

我们有一个字符串s,包含小写字母 (a-z)。我们可以用任何其他字符替换任何字符,并且可以多次这样做。

我们可以从s 生成一个回文字符串p,这样p 包含一个给定的特定单词(即假设linkedin)。现在,我们需要找到将字符串s 转换为p 所需的最少插入次数。

前 - s = linkedininininin 那么回文字符串 p 将是 linkedinnideknil 并且结果将是 6。

第二个例子(为了更清楚) - s = linkaeiouideknil 然后p = linkedinnideknil,结果将是4,因为我们将a替换为ee替换为dou替换为n

我试图通过获取 s 和 p 的 LCS 并从 s 的长度中减去它来解决它。但问题是我如何确保回文保证包含给定的单词(Linkedin)?

请提供您的方法。谢谢。

【问题讨论】:

  • 不会是 4 吗?你已经在s 中有一个ni(接近尾声)
  • 我们也需要将其设为回文
  • 为什么不简单地创建回文呢?
  • 你设法让它工作了吗?

标签: java string algorithm replace string-algorithm


【解决方案1】:

假设我正确理解了您的问题,

您可以创建回文然后替换s中的错误字母:

String s="linkaeiouideknil";
String p="";
String word="linkedin";
char[] wordC = word.toCharArray();
StringBuilder sb = new StringBuilder();
sb.append(word);
String drow = sb.reverse().toString();
sb.reverse();
sb.append(drow);
String pali=sb.toString();
char[] sC = s.toCharArray();
sC=Arrays.copyOf(sC, pali.length());
sb.delete(0, sb.length());
int counter=0;
for (int i = 0; i < sC.length; i++) {
    if(sC[i]!=pali.charAt(i)){
        sC[i]=pali.charAt(i);
        counter++;
    }
    sb.append(sC[i]);
}
System.out.println(counter);    
p=sb.toString();
System.out.println(p);

运行时的输出为4。

【讨论】:

    【解决方案2】:

    我会同时迭代字符串和回文;插入输入字符串中不存在的字符,并在有下一个可用字符时替换子字符串:

    public int palindromify(String pal, String read) {
        StringBuilder sb = new StringBuilder(read);
        int insertions = 0; //track insertions
        int palIndex = 0; //our progress through the palindrome
        //caches characters we know aren't further in the input, saves time
        Set<Character> none = new HashSet<>();
        boolean outOfInput = false;
        for (int i = 0;; i++) {
            if (i >= sb.length()) {
                outOfInput = true; //if we run out of input, we know we have to append remainder
                break;
            }
            if (palIndex >= pal.length()) {
                sb.delete(i, sb.length()); //remove remainder, we're out of palindrome
                break;
            }
            char curr = pal.charAt(palIndex++); //increment palindrome
            if (sb.charAt(i) != curr) {
                //perform lookahead
                boolean found = false;
                if (!none.contains(curr)) { //only search a missing char once
                    for (int w = i + 1; w < sb.length(); w++) {
                        if (sb.charAt(w) == curr) {
                            sb.replace(i, w + 1, "" + curr); //replace up to our lookahead
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        none.add(curr);
                    }
                }
                if (!found) {
                    //simply insert our character, later ones are useful for others
                    sb.insert(i, curr);
                    insertions++; //this was an insertion, one of our counted values
                }
            }
        }
        //if we ran out of input, append the rest of palindrome
        return insertions + (outOfInput ? pal.length() - sb.length() : 0);
    }
    

    这样可以为你节省大量的复制/迭代/不必要的工作,并且应该确保最大迭代量是读入的回文长度(或输入的长度,取较短者)

    因此调用时:

    palindromify("linkedinnideknil", "linkedinininin"); //prints '4'
    

    创建实际的回文非常简单,而且工作量少很多:

    String s = /* some value */;
    s += new StringBuilder(s).reverse();
    

    编辑:不适用于某些边缘情况,正在修复。

    【讨论】:

    • 这里的重点是p可以通过其他方式轻松构建,我避免在方法中完成p,因为返回想要的数字无论如何都会丢失它的值。
    • 好消息是我的更新答案无论如何都完全构建了它
    • @rouge,有点麻烦……但我想这只是因为这个问题可以从几个方面理解。
    【解决方案3】:

    我将首先创建您想要将字符串转换为的回文。接下来,计算从原始字符串到您创建的回文的编辑距离,您的编辑正在替换字符串中的字符:没有插入或删除。代码看起来像

    def minReplacements(original, palindrome, m, n):
        # base case:  we're finished processing either string so we're done
        if (m == 0 or n == 0):
            return 0
    
        # The characters in the string match so find out how many replacements are
        # required for the remaining characters in the strings.
        if (original[m-1] == palindrome[n-1]):
            return minReplacements(origininal, palindrome, m-1, n-1)
    
        # Recurse on replacing a character in the original string
        # with a character in the palindrome string
        return 1 + minReplacements(origininal, palindrome, m-1, n-1)
    

    另一方面,如果您想知道将原始字符串转换为回文字符串需要多少个字符替换、插入或删除,则使用以下代码更改上面代码的最后一行:

        return 1 + min(minReplacements(origininal, palindrome, m, n-1),   # insert character
                       minReplacements(origininal, palindrome, m-1, n-1), # replace character
                       minReplacements(origininal, palindrome, m-1, n))   # delete character
    

    当时的代码如下:

    def minReplacements(original, palindrome, m, n):
        # base case:  we're finished processing either string so we're done
        if (m == 0):  # done processing original string
            return n  # return the number of characters left in palindrome
        if (n == 0):  # done processing palindrome
            return m  # return the number of characters left in the original string
    
        # The characters in the string match so find out how many edits are
        # required for the remaining characters in the strings.
        if (original[m] == palindrome[n]):
            return minReplacements(origininal, palindrome, m-1, n-1)
    
        # Recurse on editing a character in the original string
        # with a character in the palindrome string
        return 1 + min(minReplacements(origininal, palindrome, m, n-1),   # insert character
                       minReplacements(origininal, palindrome, m-1, n-1), # replace character
                       minReplacements(origininal, palindrome, m-1, n))   # delete character
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-30
      • 2019-08-06
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多