【问题标题】:How do I use Java Regex to find all repeating character sequences in a string?如何使用 Java Regex 查找字符串中的所有重复字符序列?
【发布时间】:2012-05-04 11:40:01
【问题描述】:

使用 Java 和 Regex 解析随机字符串以查找重复序列。

考虑字符串:

aaabbaaacccbb

我想找到一个正则表达式,它会在上面的字符串中找到所有匹配项:

aaabbaaacccbb
^^^  ^^^

aaabbaaacccbb
   ^^      ^^

什么是正则表达式,它将检查字符串中是否存在任何重复的字符序列并返回这些重复字符的组,例如组 1 = aaa 和组 2 = bb。另请注意,我使用了示例字符串,但任何重复字符都是有效的: 罗恩乔乔 ... ... ,, ,,...,,

【问题讨论】:

  • 似乎使用像this这样的基于字典的字符串搜索算法会更好,因为你一开始不知道模式。
  • 重复序列是否需要连续? “RonBobRonJoe”是否应该返回“Ron”?
  • RonBobRonBobAbeRonBobRonBobAbeXXYYXY 应该返回什么?
  • “重复字符序列”与“重复字符序列”的意思是一样的吗?

标签: java regex pattern-matching


【解决方案1】:

这样做:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        String s = "aaabbaaacccbb";
        find(s);
        String s1 = "RonRonRonJoeJoe .... ,,,,";
        find(s1);
        System.err.println("---");
        String s2 = "RonBobRonJoe";
        find(s2);
    }

    private static void find(String s) {
        Matcher m = Pattern.compile("(.+)\\1+").matcher(s);
        while (m.find()) {
            System.err.println(m.group());
        }
    }
}

输出:

aaa
bb
aaa
ccc
bb
RonRonRon
JoeJoe
....
,,,,
---

【讨论】:

  • 实际上,这不起作用:如果您对 RonRonJoeJoe 运行它,它不会打印任何内容。
  • @ReverendGonzo 好的,我在帖子中错过了。我现在通过在 \\w 之后添加 + 来修复它
  • @ReverendGonzo 那应该是什么输出?没有重复序列,因此它不匹配任何东西
  • “罗恩”重复。我的印象是它们不需要连续。
  • @ReverendGonzo 好的,我明白你的意思了。我实际上有相反的感觉,他们应该是连续的。 OP 必须澄清这一点。
【解决方案2】:

以下内容应适用于所有要求。它实际上是这里的几个答案的组合,它会打印出字符串中其他任何地方重复的所有子字符串。

我将其设置为仅返回至少 2 个字符的子字符串,但可以通过将正则表达式中的“{2,}”更改为“+”轻松将其更改为单个字符。

public static void main(String[] args)
{
  String s = "RonSamJoeJoeSamRon";
  Matcher m = Pattern.compile("(\\S{2,})(?=.*?\\1)").matcher(s);
  while (m.find())
  {
    for (int i = 1; i <= m.groupCount(); i++)
    {
      System.out.println(m.group(i));
    }
  }
}

输出:
罗恩
山姆

【讨论】:

  • 但是你如何计算每个字符串在文件中的元素数量,为什么它的 kmer 总是 3?
【解决方案3】:

您可以使用这个基于positive lookahead 的正则表达式:

((\\w)\\2+)(?=.*\\1)

代码:

String elem = "aaabbaaacccbb";
String regex = "((\\w)\\2+)(?=.*\\1)";
Pattern p = Pattern.compile(regex);
Matcher matcher = p.matcher(elem);
for (int i=1; matcher.find(); i++)
System.out.println("Group # " + i + " got: " + matcher.group(1));

输出:

Group # 1 got: aaa
Group # 2 got: bb

【讨论】:

    【解决方案4】:

    这似乎有效,尽管它也给出了子序列:

    (公平地说,这是根据 Guillame 的代码构建的)

    public static void main(final String[] args) {
        // final String s = "RonRonJoeJoe";
        // final String s = "RonBobRonJoe";
        final String s = "aaabbaaacccbb";
    
        final Pattern p = Pattern.compile("(.+).*\\1");
    
        final Matcher m = p.matcher(s);
        int start = 0;
        while (m.find(start)) {
            System.out.println(m.group(1));
            start = m.toMatchResult().end(1);
        }
    }
    

    【讨论】:

      【解决方案5】:

      您可以忽略重叠。

      // overlapped 1 or more chars
      (?=(\w{1,}).*\1)
      // overlapped 2 or more chars
      (?=(\w{2,}).*\1)
      // overlapped 3 or more chars, etc ..
      (?=(\w{3,}).*\1)
      

      或者,你可以消费(非重叠)..

      // 1 or more chars
      (?=(\w{1,}).*\1) \1
      // 2 or more chars
      (?=(\w{2,}).*\1) \1
      // 3 or more chars, etc ..
      (?=(\w{3,}).*\1) \1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-18
        • 2012-04-20
        • 1970-01-01
        • 1970-01-01
        • 2012-01-25
        • 2011-04-15
        相关资源
        最近更新 更多