【问题标题】:Find out recursive pattern in a string java找出字符串java中的递归模式
【发布时间】:2017-11-10 09:06:59
【问题描述】:

在我的一次采访中,我问过一个关于 java 字符串的程序,我无法回答。我不知道这是一个简单的程序还是复杂的程序。我已经在互联网上进行了探索,但无法找到确切的解决方案。我的问题如下,

我假设一个字符串包含递归模式,例如,

String str1 = "abcabcabc";

上面的字符串递归模式是在一个字符串中重复的“abc”,因为这个字符串递归地只包含“abc”模式。

如果我将此字符串作为参数传递给函数/方法,该函数/方法应返回我 “此字符串具有递归模式。” 如果该字符串没有任何递归模式,则简单的函数/方法应该返回“这个字符串不包含递归模式。”

以下是概率,

String str1 = "abcabcabc"; 
//This string contains recursive pattern 'abc'

String str2 = "abcabcabcabdac"; 
//This string doesn't contains recursive pattern

String str2 = "abcddabcddabcddddabc";
//This string contains recursive pattern 'abc' & 'dd'

任何人都可以为此建议我解决方案/算法,我正在努力解决这个问题。不同概率的最佳方法是什么,以便我实施?

【问题讨论】:

  • 这与递归有什么关系?一个重复的模式,当然,但是递归?
  • 在您的第三个字符串中有abcdd 以及dddd。这是否意味着可以以任何方式混合超过 1 种模式?
  • 你的第二个字符串包含 a, b, c, ab, bc, abc, ... 作为重复字符串
  • 你需要一个正则表达式,我相信,if (s.matches("^(abc|dd)+$") {return true;} else { return false; }
  • 数列的“递归模式”类似于“A(n) = A(n - 1) + k”,例如 1, 4, 7, 10, ... (k = 3)。不确定如何轻松将其扩展到字符串。很确定他们的意思是“重复模式”或类似的。

标签: java string algorithm data-structures pattern-matching


【解决方案1】:

来自LeetCode

public boolean repeatedSubstringPattern(String str) {
  int l = str.length();
  for(int i=l/2;i>=1;i--) {
      if(l%i==0) {
          int m = l/i;
          String subS = str.substring(0,i);
          StringBuilder sb = new StringBuilder();
          for(int j=0;j<m;j++) {
              sb.append(subS);
          }
          if(sb.toString().equals(str)) return true;
      }
  }
  return false;
}
  1. 重复子串的长度必须是输入串长度的除数
  2. 搜索 str.length 的所有可能除数,从 length/2 开始
  3. 如果 i 是长度的除数,则重复从 0 到 i 的子字符串 i 包含在 s.length 中的次数
  4. 如果重复的子字符串等于输入的str,则返回true

【讨论】:

  • 确实如此。我觉得OP没有准确地描述问题。该问题要求检查字符串中是否存在重复模式,而不是重复模式。 leetcode.com/problems/repeated-substring-pattern/description
  • 没有。它没有。我同意第三个示例中可能存在拼写错误,但您提供的代码与该示例不匹配。对问题的描述肯定有一些缺失,但仅仅因为它表面上看起来像是查找字符串重复的问题并不意味着这是解决方案。
【解决方案2】:

解决方案不在 Javascript 中。但是,问题看起来很有趣,因此尝试在python 中解决它。道歉!

python,我写了一个有效的逻辑[可以写得更好,认为逻辑会帮助你]

脚本是

def check(lst):
    return all(x in lst[-1] for x in lst)

s = raw_input("Enter string:: ")
if check(sorted(s.split(s[0])[1:])):
    print("String, {} is recursive".format(s))
else:
    print("String, {} is NOT recursive".format(s))

脚本的输出:

[mac] kgowda@blr-mp6xx:~/Desktop/my_work/play$ python dup.py 
Enter string:: abcabcabcabdac
String, abcabcabcabdac is NOT recursive
[mac] kgowda@blr-mp6xx:~/Desktop/my_work/play$ python dup.py 
Enter string:: abcabcabc
String, abcabcabc is recursive
[mac] kgowda@blr-mp6xx:~/Desktop/my_work/play$ python dup.py 
Enter string:: abcddabcddabcddddabc
String, abcddabcddabcddddabc is recursive

【讨论】:

    【解决方案3】:

    这也可以使用Knuth–Morris–Pratt Algorithm的一部分来解决。

    这个想法是建立一个一维数组,每个条目代表单词中的一个字符。对于单词中的每个字符i,我们检查是否有前缀也是单词up 0 to i 中的后缀。原因是如果我们有共同的后缀和前缀,我们可以继续从前缀结束后的字符开始搜索,我们用相应的字符索引更新数组。

    对于s="abcababcababcab",数组将是

    Index : 0 1 2 3 4 5 6 7 8 
    String: a b c a b c a b c 
    KMP   : 0 0 0 1 2 3 4 5 6 
    

    对于Index = 2,我们看到没有后缀,它也是字符串ab 中的前缀,即)直到Index = 2

    对于Index = 4,后缀ab(Index = 3, 4) 与前缀ab(Index = 0, 1) 相同,因此我们更新KMP[4] = 2,这是我们必须从中获取的模式的索引继续搜索。

    因此KMP[i] 保存字符串s 的索引,其中前缀匹配0 to i 范围内的最长后缀加1。这实质上意味着长度为index + 1 - KMP[index] 的前缀存在于先前的字符串中。使用此信息,我们可以找出该长度的所有子字符串是否相同。

    对于Index = 8,我们知道KMP[index] = 6,这意味着有一个长度为9 - 6 = 3的前缀(s[3] to s[5])等于后缀(s[6] to s[8]),如果这是我们唯一重复的模式有这个会跟随

    有关此算法的更清晰说明,请check this video lecture。 这张表可以在线性时间内建立,

    vector<int> buildKMPtable(string word)
    {
        vector<int> kmp(word.size());
        int j=0;
        for(int i=1; i < word.size(); ++i)
        {
            j = word[j] == word[i] ? j : kmp[j-1];
            if(word[j] == word[i])
            {
                 kmp[i] = j + 1;
                ++j;
            }
            else
            {
                kmp[i] = j;
            }
        }
        return kmp;
    }
    
    bool repeatedSubstringPattern(string s) {
        auto kmp = buildKMPtable(s);    
        if(kmp[s.size() -1] == 0) // Occurs when the string has no prefix with suffix ending at the last character of the string
        {
            return false;
        }
        int diff = s.size() - kmp[s.size() -1]; //Length of the repetitive pattern
        if(s.size() % diff != 0) //Length of repetitive pattern must be a multiple of the size of the string
        {
            return false;
        }
    // Check if that repetitive pattern is the only repetitive pattern. 
        string word = s.substr(0, diff);
        int w_size = word.size();
        for(int i=0; i < w_size; ++i)
        {
            int j = i;
            while(j < s.size())
            {
                if(word[i] == s[j])
                {
                    j += w_size;    
                }
                else
                {
                    return false;
                }
            }
        }
        return true;
    }
    

    【讨论】:

      【解决方案4】:

      如果你事先知道“零件”,那么答案可能是Recursive regular expressions,看来。

      所以对于abcabcabc,我们需要像abc(?R)* 这样的表达式,其中:

      • abc 匹配文字字符
      • (?R) 递归模式
      • 一个 * 匹配零次到无限次

      第三个有点棘手。请参阅this regex101 link,但它看起来像:

      ((abc)|(dd))(?R)*

      我们有 'abc' 或 'dd' 并且有任意数量。

      否则,我看不出你怎么能从一个字符串中确定它有一些像这样的未定义的递归结构。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-30
        • 1970-01-01
        • 2016-10-02
        • 2014-02-19
        • 2020-03-15
        相关资源
        最近更新 更多