The original problem of Leetcode Wordbreak
Given A string s and a Dictionary of words dict, determine if s can segmented into a space-s Eparated sequence of one or more dictionary words.
For example, given
s = "leetcode" ,
dict = ["leet", "code"] .
Return true because "leetcode" can be segmented as "leet code" .
0, Problem Introduction
Given a dictionary that contains several words, and a string that splits the string, the resulting word must consist of words in the dictionary.
1, the introduction of dynamic planning---the analysis of dynamic programming with reference to the introduction to the algorithm to analyze This problem
① Optimal sub-structure
To determine whether the entire string s[0..length-1] can be divided, the first to determine whether s[0...length-1] can be divided, and judge S[0...length-1] can be divided, can be first sentenced to s[0...length-2] can be divided, ... Until the s[0] can be divided, and s[0] can be split is obvious---(Find s[0] in the dictionary can--dict.contains (s[0])???)
The recursive expression is as follows:
What is the total number of ② problems? How many choices can I have for each sub-problem? What is the time complexity of the algorithm?
The number of sub-problems one has n, and n is the length of the string. There are 2 choices for each sub-problem, that is, it can be split, or it cannot be split. From this point of view, the time complexity of the algorithm is O (n). However, how many steps do you need to take to make a choice for each sub-question, and how much does it cost? As can be seen from the line 18th for loop in the code below, I need to loop I for sub-problem, then the time complexity is 1+2+3+......+n = O (n^2).
③ used to overlap sub-problems in dynamic programming
Overlapping sub-problem in dynamic programming means that in the process of decomposing the original problem, some sub-problems are obtained, and then the sub-problems are decomposed, and some more problems are obtained. Many of these sub-problems are repetitive. This feature is different from the decomposition problem of divide-and-conquer algorithm, the sub-problem of splitting and resolving algorithm is generally independent, and there is not much connection between the sub-problems. based on the repeatability of the dynamic programming sub-problem, after solving a sub-problem, the result of it is recorded, and the next time we encounter this problem, we can find its result directly, instead of calculating the sub-problem again.
In the analysis of the 2nd dynamic Programming solution in the Wordbreak problem (2nd below), the value of solving match[i] may need to be match[i-1], match[i-2] 、...... match[0];
The value for solving match[i-1] may need to be match[i-2], match[i-3], match[0]. Match[i] that corresponds to s[0..i-1] can divide the problem, combined with the dynamic programming from the bottom up to solve the problem of the nature of the "bottom" problem of the results recorded, in the solution to the "upper" problem, find the "bottom" problem, this way can improve the efficiency of the algorithm operation. This is also the "Introduction to the algorithm" in the problem of LCS referred to the "look-up table." The specific code is as follows: What is the value to find Match[j] when you want the value of Mathc[i]?
for (int i = 1; i < length + 1; i++) { for (int j = 0; J < i; j + + ) { if (match[j] && worddict.contains (s.substring (J, i))) { true;
2, using dynamic programming to solve the idea
①match[s.length] is used to represent the string s[0...length-1] each part can be split. Initial time, Match[0]=true; Match[i] Indicates whether the character s[0...i-1] can be split.
Match[s.length] Indicates whether the entire string (S[0...length-1]) can be split.
② if match[i]=true, which means s[0...i-1] is capable of splitting, it is required to meet any of the following conditions: one by one
A) match[0]==true && s[0...i-1] in the dictionary; b) match[1] = = True && s[1...i-1] in the dictionary; c) match[2] = = True && s[ 2...i-1] in the dictionary;
d) match[i-1]==true && s[i-1] in the dictionary. S[I...J] is represented in the dictionary: the substring in the string s from the subscript I to J is a word in the dictionary.
Specific analysis: set S = "AAAAA", dict = ["AAAA", "AAA"]
Because "a" is not in dict, so match[1] = false; "AA" is not in Dict and (Match[1]=false && "A" is not in dict), so match[2]=false, for the value of match[3],
First judge whether "AAA" in the Dict, because "AAA" in the Dict, so match[3] = True, for match[4], because "AAAA" in dict match[4] = True,
For Match[5], first Judge "AAAAA", because it does not belong to Dict, and then continue to judge, (match[1] = true?) and (s[1...5] exist in Dict?), although, s[1...5]= "AAAA" exist in DIC T is true, but match[1] = false, and therefore cannot be judged match[5];
" AAAAA " " a " " AAAA " "a" is not in Dict because, match[1false Although "AAAA" is in Dict, But it can't be so, because "a" is not in Dict.
So match[2] is assigned false
Continue to judge, (match[2] = true?) and (s[2...5] exist in dict?) ....
" AAAAA " " AA " " AAA " "aa" is not in Dict, because judging match[2false" aaa" in the dict, but still can't so match[3] false
Until it is judged that
Match[4]==true? and s[4...4] = = "A" exist in Dict?? At this point, although match[4] = = true but s[4]== "a" is false, match[5]= false.
That is, for set S = "AAAAA", dict = ["AAAA", "AAA"], the program will return false.
3, the complete code is as follows:
1 ImportJava.util.HashSet;2 ImportJava.util.Set;3 4 Public classSolution {5 6 Public BooleanWordbreak (String s, set<string>worddict) {7 //parameter Check8 if(s = =NULL|| S.length () < 1 | | Worddict = =NULL|| Worddict.size () < 1) {9 return false;Ten } One A //whether the tag matches, Match[i] represents str[0, i-1] can be split - intLength =s.length (); - Boolean[] match =New Boolean[Length + 1]; theMatch[0] =true; - - for(inti = 1; I < length + 1; i++) { - for(intj = 0; J < I; J + +) { + if(Match[j] &&Worddict.contains (S.substring (J, i))) { - //s (0,n) = S (0,i) + S (i,j) + S (j,n) +Match[i] =true; A Break; at } - } - } - returnMatch[length]; - } - Public Static voidMain (string[] args) { inSolution s =Newsolution (); -Set<string> set =NewHashset<string>(); toSet.add ("AAAA"); +Set.add ("AAA"); - Booleanresult = S.wordbreak ("AAAAA", set); the System.out.println (result); * } $ Panax Notoginseng}
The idea of dynamic programming to solve the problem of string segmentation