【问题标题】:Find all consecutive repetition in a String java在String java中查找所有连续重复
【发布时间】:2016-12-02 18:28:25
【问题描述】:

我必须实现一个算法来查找字符串中的所有连续重复。

因此,例如,给定 String = a a 1a a 1 生成一种类似 ((a )+1)+ 的正则表达式。

我试图应用递归算法,但在网上什么也没找到。最后,它似乎是一个简单 DFA 的实现。

一些帮助?谢谢。

【问题讨论】:

  • 预期输出是什么?
  • Regex (\b\w+\b)\s+((?:\s*\b\1\b)+) 可能会这样做,其中捕获组 2 是“连续重复”,例如它捕获示例字符串中的第二个a。请参阅regex101 进行演示。
  • 那么你发现了什么?

标签: java string dfa


【解决方案1】:

解决方案

伪代码:

for every combination of two adjacent substrings of equal length
    if the two adjacent substrings are equal
        add the substring to a set of consecutive repetitions

解释:

set 很重要,以避免添加任何特定连续重复的多个实例。但是,如果这是您想要做的,那么理论上您可以使用任何数据结构。 (但multiset 可能是最好的......请参阅 Google Guava 的 multiset

注意for 循环遍历每个组合,而不是排列。这是因为您的问题陈述暗示顺序无关紧要(这是真的吗?)。

实际上迭代两个相等长度的相邻子字符串的每个组合的最简单方法可能是使用两个嵌套循环。这一步也可以优化(例如,可能带有记忆)。



示例代码

for (int begin = 0; begin < string.length() - 1; ++begin) {
    for (int end = begin; end < (string.length() + begin) / 2; ++end) {

        substring_1 = string.substring(begin, end+1);
        substring_2 = string.substring(end+1, end+1 + substring_1.length());

        if (substring_1.equals(substring_2)) {
            set.add(substring_1);
        }
    }
}

关于示例代码的一些说明:

  • beginend 索引用于 substring_1
  • substring_2 是与substring_1 连续的等长子串。
  • substring(int,int) 方法包括开始索引并排除结束索引。因此上面的语义。
  • “开始”for 循环不包括字符串中的最后一个索引。这是因为由该索引处的字符组成的非空子字符串没有非空连续子字符串。
  • “结束”for 循环在begin 和字符串结尾之间的中点处停止。这是因为任何从 begin 开始并且比这更长的子字符串都没有等长的连续子字符串。

更多优化:

  • 为避免每次迭代生成两个新的 String 对象来表示 substring_1 和 substring_2 的开销,请改用 regionMatches(int,String,int,int) 方法。调用此方法的字符串和“其他”字符串参数都将是相同的(原始的、全长的)字符串。

例如:

for (offset1 = 0; offset1 < string.length() - 1; ++offset1) {
    for (len = 1; len < ((string.length() - offset) / 2) + 1; ++len) {

        offset2 = offset1 + len;

        if (string.regionMatches(offset1, string, offset2, len)) {
            set.add(string.substring(offset1, offset1 + len));
        }
    }
}

【讨论】:

  • 如果您通过谷歌搜索来到这里并正在寻找 java(script) 解决方案,这里是代码 jsfiddle.net/xwem39sL
【解决方案2】:

首先将字符串划分为字符,然后使用循环检查相似性:

String txt = "text";
char chars[] = txt.toCharArray();
for(int i =0; i < chars.length; i++){
    if(i>0){
        if(chars[i] == chars[i-1]) {
             System.out.println(i + " and" + (i-1) + "are similar");
        }
    }
}

这只是一个你可以完善它的例子。

【讨论】:

  • 我相信任务是找到以空格分隔的单词的重复,而不是直接相邻的字符。查看示例:a a 1a a 1。它没有重复的字符,但确实有一个重复的单词:a
  • 这就是为什么我说:你可以完善它而不是这是最终的答案
  • 写出完全不同的东西并不是“完善它”。您的代码适用于单独的字符 (char),但解决方案需要适用于单词 (String)。
  • @Andreas 你需要做的只是用字符串数组替换字符数组并稍微改变比较。
  • 是的,如果你想使用单词而不是字符,你需要txt.toCharArray(),我说“稍微改变比较”,它涵盖了== 的问题。所以我同意这不是问题的确切解决方案,但这是一个很好的起点。它显示了算法。
猜你喜欢
  • 2016-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多