递归?字符串中的组合

时间:2015-04-18 23:54:03

标签: java string recursion dynamic-programming

我现在已经处理了以下递归问题一段时间了,并且无法解决这个问题。基本上,你有一些由某些单词构成的句子,其中所有单词都只是卡在一起,没有间隔开。我们的想法是找到可用于创建句子的所有可能单词组合的数量。

例如,

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

另一个例子:

  • 单词:ooga,oogam,oogum,mook,ook
  • 句子: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;
}

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

2 个答案:

答案 0 :(得分:2)

1)正确命名您的方法,&#34; WAYS&#34;是一个常量名称,而不是方法名称。

2)提供可运行的代码,特别是在代码太短的情况下。

3)切勿将异常用于控制流程。

4)你正在使用魔法值,如&#34; uug&#34;和&#34; ook&#34;在你的代码?这看起来简单明了吗?这看起来可以维护吗?如果你得到一个包含数百万个不同单词的词典,这应该是什么样的呢?

编辑:给出完整的列表有点无聊,所以我留下了一些空白。尽量填补这些,希望有所帮助。

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()来获取单词的大小。

答案 1 :(得分: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),你当前的尝试比目标序列更长(或相同长度但不相等),因此没有任何意义继续搜索它。

你必须记住的是道路 - &#34;我是怎么来到这里的?&#34;列表(回溯)。