【问题标题】:Recursion? Combinations in a String递归?字符串中的组合
【发布时间】:2015-06-25 18:46:26
【问题描述】:

我一直在处理以下递归问题,但一直无法弄清楚。基本上,您有某种由某些单词组成的句子,其中所有单词只是卡在一起,而不是间隔开。这个想法是找到可用于创建句子的所有可能的单词组合的数量。

例如,

  • 单词:ok,okook
  • 句子:ookookook
  • 解决方案:{ook, ook, ook}, {ookook, ook}, {ook, ookook}。

另一个例子:

  • 单词:ooga、oogam、oogum、mook、ok
  • 句子:oogamookoogumook
  • 解决方案:{ooga, mook, oogum, ook}, {oogam, ook, oogum, ook}

我尝试了很多东西,最后放弃并尝试手动完成......

public static int WAYS(String word) {
    int ways = 1;
    for (int i = 0; i < word.length(); i++) {
        try{
            if(word.substring(i, i - 2).equals("ug")){
                if(word.substring(i - 4, i - 2).equals("ug")){
                    ways++;
                }
            }
            else if(word.substring(i, i - 3).contains("ook")){
                System.out.println(word.substring(i-6, i-3));
                if(word.substring(i - 6, i - 3).equals("ook")){
                    ways++;
                }
                if(word.charAt(i - 4) == 'm'){
                    if(word.substring(i - 8, i - 4).equals("ooga") || word.substring(i - 8, i - 4).equals("oogu")){
                        ways++;
                    }
                }
            }
            else if(word.substring(i, i - 4).contains("mook")){
                if(word.substring(i - 8, i - 4).contains("mook")){
                    ways++;
                }
            }
            if(word.substring(i, i - 2).equals("oog")){
                if(word.charAt(i + 2) == 'm'){
                    if(word.charAt(i + 1) == 'a' || word.charAt(i + 1) == 'u'){
                        ways++;
                    }
                }
            }
        } catch(Exception e){
            continue;
        }
    }
    return ways;
}

但它没有奏效。有人可以给我一个关于使用递归解决这个问题的想法或示例吗?

【问题讨论】:

  • 你能展示你的递归尝试吗?你真的,真的需要在这个问题上使用递归。像您发布的那样的非递归解决方案是行不通的。
  • @JohnKugelman 我的递归尝试真的很糟糕,因为我不明白如何用递归正确解决这个问题。我只需要了解如何处理这些类型的问题的基础知识。

标签: java string recursion dynamic-programming


【解决方案1】:

希望 VB.NET 代码不会介意,只是为了掌握。

Private Sub Go()
    Dim words As New List(Of String)

    words.Add("ooga")
    words.Add("oogam")
    words.Add("oogum")
    words.Add("mook")
    words.Add("ook")

    Search("oogamookoogumook", words, "", New List(Of String))
End Sub

Private Sub Search(ByVal sentence As String, _
                        ByVal wordList As List(Of String), _
                        ByVal actualSentenceBuildingState As String, _
                        ByVal currentPath As List(Of String))

    For Each word As String In wordList
        Dim actualSentenceAttemp As String
        Dim thisPath As New List(Of String)(currentPath)

        thisPath.Add(word)
        actualSentenceAttemp = actualSentenceBuildingState + word

        If actualSentenceAttemp = sentence Then
            Debug.Print("Found: " + String.Join("->", thisPath.ToArray()))
        End If

        If actualSentenceAttemp.Length < sentence.Length Then 'if we are not too far, we can continue
            Search(sentence, wordList, actualSentenceAttemp, thisPath)
        End If
    Next
End Sub

打印输出:

Sentence: oogamookoogumook
Found: ooga->mook->oogum->ook
Found: oogam->ook->oogum->ook

Sentence: ookookook
Found: ook->ook->ook
Found: ook->ookook
Found: ookook->ook

把它想象成在图表中行走(实际上就是这样)。你什么都没有开始(空字符串)。现在您开始迭代地将单词列表中的单词添加到您的“当前句子尝试”中。将单词添加到当前尝试后,您只能以三种可能的状态结束:(1)您得到了最后一个句子,(2)当前尝试比目标句子短,因此仍然适合添加下一个单词(递归调用),或者( 3),您当前的尝试比目标序列长(或长度相同但不相等),因此继续搜索它没有意义。

你必须记住的是路径——“我是怎么到这里的?”列表(回溯)。

【讨论】:

    【解决方案2】:

    1) 正确命名您的方法,“WAYS”是一个常量名称,而不是方法名称。

    2) 提供可运行的代码,尤其是在它很短的情况下。

    3) 永远不要对控制流使用异常。

    4) 您在代码中使用了诸如“uug”和“ook”之类的魔法值?这看起来简单明了吗?这看起来可以维护吗?如果你得到一个包含一百万个不同单词的词典,这应该是什么样子?

    编辑:给出完整的列表有点无聊,所以我留下了一些空白。尝试填写这些内容,希望对您有所帮助。

    public class JammedWords {
      public static int ways(String sentence, String[] words) {
        if (sentence.isEmpty()) {
          // The trivial case: the sentence is empty. Return a single number.
        } else {
          int c = 0;
          for (String w: words) {
            if (sentence.startsWith(w)) {
              // call method recursively, update counter `c`.
            }
          }
          return c;
        }
      }
      public static void main(String[] args) {
        System.out.println(ways("ookookook", new String[]{"ook", "ookook"}));
        System.out.println(ways("oogamookoogumook", new String[]{"ooga","oogam","oogum","mook","ook"}));
      }
    }
    

    提示:

    A) 了解空集、包含空集的集合、包含包含空集的集合等的区别。包含空集的集合当然不是空的,它们的大小也不为0。

    B) 有一个方便的方法 String.substring(n) 可以删除第 n 个字符之前的所有内容。并且有 String.length() 来获取单词的大小。

    【讨论】:

    • 感谢您的想法和提示!
    猜你喜欢
    • 2012-04-17
    • 2023-04-02
    • 1970-01-01
    • 2021-11-19
    • 2021-02-14
    • 2019-07-24
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    相关资源
    最近更新 更多