4

我正在尝试使用正则表达式解决编码蝙蝠问题,无论它是否适用于网站。

到目前为止,我有以下代码,它没有*在两个连续的相等字符之间添加 a。相反,它只是推倒它们并用一组字符串替换它们。

public String pairStar(String str) {
    Pattern pattern = Pattern.compile("([a-z])\\1", Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    if(matcher.find())
    matcher.replaceAll(str);//this is where I don't know what to do
    return str;
}

我想知道如何继续使用正则表达式并替换整个字符串。如果需要,我认为递归系统可以提供帮助。

4

4 回答 4

2

这有效:

while(str.matches(".*(.)\\1.*")) {
    str = str.replaceAll("(.)\\1", "$1*$1");
}
return str;

正则表达式的解释:

搜索正则表达式(.)\\1

  • (.)表示“任何字符”(的.)和括号创建一个组 - 组 1(第一个左括号)
  • \\1,在正则表达式中是\1(java文字String必须用另一个反斜杠转义反斜杠)表示“第一组” - 这种术语称为“反向引用”

所以一起(.)\1意味着“任何重复的字符”


替换正则表达式$1*$1

  • $1术语的意思是“作为第 1 组捕获的内容”


递归解决方案:

从技术上讲,该站点要求的解决方案是递归解决方案,因此这里是递归实现:

public String pairStar(String str) {
    if (!str.matches(".*(.)\\1.*")) return str;
    return pairStar(str.replaceAll("(.)\\1", "$1*$1"));
}
于 2012-12-06T01:22:32.360 回答
1

我不知道java,但我相信java中的字符串或正则表达式有替换函数。您的匹配字符串将是

([a-z])\\1

而替换字符串将是

$1*$1

经过一番搜索,我认为您正在寻找这个,

str.replaceAll("([a-z])\\1", "$1*$1").replaceAll("([a-z])\\1", "$1*$1");
于 2012-12-06T01:13:58.097 回答
1

FWIW,这是一个非递归解决方案:

public String pairStar(String str) {
  int len = str.length();
  StringBuilder sb = new StringBuilder(len*2);
  char last = '\0';
  for (int i=0; i < len; ++i) {
    char c = str.charAt(i);
    if (c == last) sb.append('*');
    sb.append(c);
    last = c;
  }
  return sb.toString();
}
于 2012-12-06T18:42:26.323 回答
1

这是我自己的解决方案。

递归解决方案(可能或多或少是问题设计的解决方案)

public String pairStar(String str) {
    if (str.length() <= 1) return str;
    else return str.charAt(0) +
                (str.charAt(0) == str.charAt(1) ? "*" : "") +
                pairStar(str.substring(1));
}

如果您想抱怨substring,那么您可以编写一个辅助函数pairStar(String str, int index)来执行实际的递归工作。

正则表达式单行一函数调用解决方案

public String pairStar(String str) {
  return str.replaceAll("(.)(?=\\1)", "$1*");
}

两种解决方案具有相同的精神。他们都检查当前字符是否与下一个字符相同。如果它们相同,则*在 2 个相同的字符之间插入 a。然后我们继续检查下一个字符。a*a*a*a这是从 input产生预期的输出aaaa

的正常正则表达式解决方案"(.)\\1"有一个问题:每次匹配消耗 2 个字符。结果,我们无法比较第二个字符之后的字符是否是同一个字符。前瞻用于解决这个问题——它将与下一个字符进行比较而不消耗它。

这类似于递归解决方案,我们比较下一个字符str.charAt(0) == str.charAt(1),同时在子字符串上递归调用函数,只删除当前字符pairStar(str.substring(1)

于 2013-05-08T20:04:03.510 回答