The dynamic programming idea is an important idea in algorithm design, so-called dynamic programming is "to look at the side of the road", the front of the know, the back of the front can also be pushed out. And the divide-and-conquer algorithm is similar and different, the same is the need to find the optimal sub-structure, repeat sub-problems, boundary conditions. The difference is that the dynamic programming algorithm stores each of the preceding results, and the subsequent results are pulled down by the previous results. Divide and conquer are divided, solve the problem separately, and then merge. There is no transition relationship between the previous and two States (think of quick sorting and LCS), and the fast sorting method is a typical application of divide-and-conquer. in layman's terms, dynamic programming is essentially a planning, a constant decision-making problem that is generally used to solve the most important values, and division is a way to deal with complex problems, not just to solve the most-valued problems.
First of all, the dynamic planning, which is the most important of the five algorithm ideas is also very common, in the future blog, I will slowly update the other four of the analysis of the idea of the algorithm.
Dynamic planning has several important components :
1. Optimal sub-structure: if the optimal solution of the problem contains sub-problems of the solution is also optimal, it is said that the problem has the best sub-structure
2. Overlapping sub-problem: You find the optimal substructure we want to transform it into overlapping sub-problem, the same method of cyclic solution
3. State transition equation: Every sub-problem you find can be thought of as a planning problem in a state, and you need to find the correlation equation between state and state, so that we can solve the more complex states that need to be solved from the simplest state loops.
4. Boundary conditions: That is, the initial value of the sub-problem, you must give some small sub-problems of the initial value to open the cycle, or can not be solved by cyclic
4. Sub-Problem Independence: Independent problem, mainly sub-problem of each object independent, do not occur a sub-problem in the operation of the changes in another sub-problem variables in the case, specifically see my recursive mode of thinking a article
5. No effect: Once a stage state is determined, it is no longer affected by subsequent state decisions. That is, the process after a state does not affect the previous state, only the current state.
The problem has the optimal substructure , which can be decomposed into a repeating sub-problem , which is the nature of the problem that wants to use DP.
----------------------------------I'm a split line ~---------------------------------
This paper first introduces the common problems of a class of dynamic programming-- string and sequence (string must be continuous, sequence can be discontinuous)
1. Longest common sub-sequence (LCS):
Overlapping sub-problem (hereafter called State): Set array dp[m][n] to represent the longest common subsequence length of str1 with length m and str2 of length n
State transition equation:if(Str1[m]==str2[n]) dp[m][n]=dp[m-1][n-1]+1;
if (Str1[m]!=str2[n]) Dp[m][n]=max (dp[m-1][n],dp[m][n-1]);
Boundary conditions (initial conditions): dp[i][0]=0 dp[0][j]=0 0<=i<=m 0<=j<=n
Satisfies optimal substructure and no-effect
2. Longest common substring (LCS):
State: Set array dp[m][n] to represent the longest common substring length of str1 and str2 ending with str1[m], and the longest length is the largest element value in Dp[m][n]
State transition equation:if(Str1[m]==str2[n]) dp[m][n]=dp[m-1][n-1]+1;
if (Str1[m]!=str2[n]) dp[m][n]=0;
Initial conditions: dp[i][0]=0 dp[0][j]=0 0<=i<=m 0<=j<=n
Satisfies optimal substructure and no-effect
3. Maximum increment subsequence (LIS):
Lis problems can be accomplished using sort +lcs problems, and dynamic programming is possible, and these time complexities are N2
State: Sets the length of the longest increment sequence in a sequence ending with an array of dp[m], and the final LIS length is the maximum value in the DP array
State transition equation: dp[i]: for (int j=1;j<i;j++) { if(A[j-1]<=a[i-1]&&dp[j]>max) max=dp[j];} DP [I]=max+1;
Initial conditions: dp[0]=0;
Satisfies optimal substructure and no-effect
4. Editing distance issues:
Status: Set Edit[m][n] for the length of M str1 and the length of N of the str2 of the editing distance
State transition equation:if(j>i) edit[i][j]=edit[i][i]+j-i; else if (j<i) Edit[i][j]=edit[j][j]+i-j; Else { If(Str1.charat (i-1) ==str2.charat (j-1)) edit[i][j]=edit[i-1][j-1]; else edit[i][j]=edit[i-1][j-1]+1;}
Initial conditions: for (int i=0;i<=m;i++) edit[i][0]=i; for (int j=0;j<=n;j++) edit[0][j]=j;
-------------------------------------------------The following two questions are not DP issues, but also a string/ Sequence Problem------------------------------------------
5. Determine if it is a subsequence: Boolean issubseq (String str1,string str2)
6. Determine if it is a substring: contains (String str) method: This problem is not as simple as imagined, involving the KMP algorithm, there is about KMP algorithm I will explain later
-----------------------------------------------------------------------below for the program--------------------------------------------- ------------------------
The above six questions, the following are all implemented in Java, where problem 3 gives two methods, because DP is a bit slow to N2 complexity, the new method is Nlogn complexity.
Import Java.util.logging.Logger;
public class Soulution {//1. Longest common sub-sequence (LCS): publicly static int LCS (String str1,string str2) {int m=str1.length ();
int N=str2.length ();
Int[][] Dp=new int[m+1][n+1];
if (Str1.charat (i) ==str2.charat (j)) dp[i][j]==dp[i-1][j-1]+1; else Dp[i][j]=max (Dp[i-1][j],dp[i][j-1]) for (int. i=1;i<=m;i++) {for (int j=1;j<=n;j++) {if (Str1.charat (i-1
) ==str2.charat (j-1)) dp[i][j]=dp[i-1][j-1]+1;
else Dp[i][j]=math.max (dp[i-1][j],dp[i][j-1]);
}} return dp[m][n];
}//2. Longest common substring (LCS): public static int lcstring (string str1,string str2) {int m=str1.length ();
int N=str2.length ();
int longest=0; Int[][] Dp=new int[m+1][n+1];
LCS for (int i=1;i<=m;i++) {for (int j=1;j<=n;j++) {if (Str1.charat (i-1) ==str2.charat (j-1)) representing two substrings with a length of MN
dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=0;
Longest=math.max (longest, dp[i][j]);
}} return longest; }//3. Maximum increment subsequence (LIS): Dynamic programming N2 solution public static int LISDP (int[] a) {int[] dp=new int[a.length+1];
int res=0;
for (int i=1;i<a.length+1;i++) {int max=0;
for (int j=1;j<i;j++) {if (A[j-1]<=a[i-1]&&dp[j]>max) max=dp[j];
} dp[i]=max+1;
if (Res<dp[i]) res=dp[i];
} return res;
}//3. Maximum increment subsequence (LIS) Nlogn solution://lis has dynamic planning and LCS to LIS (sort +lcs) Two N2 methods, there is a Nlogn method as follows://Construct an LIS (itself is not the original LIS), guaranteed the last bit.
static int len=0;
public static int LIS (int[] arr) {int[] lis=new int[arr.length]; LIS[0]=ARR[0];
The current LIS sequence length is 1, at the end of Arr[0] len=1;
for (int i=1;i<arr.length;i++) {if (arr[i]>=lis[len-1]) {lis[len]=arr[i];
len++;
} else{Lis[binarysearch (LIS, arr[i])]=arr[i];
}} return len;
} private static int BinarySearch (int[] a,int key) {int left=0;
int right=len-1;
int mid= (left+right)/2;
while (left<right) {mid=left+ (right-left)/2;
if (A[mid]<key) left=mid+1;
else Right=mid; } return left;//right is also OK}//4. Editing distance problem: public static intEditdis (String str1,string str2) {int m=str1.length ();
int N=str2.length (); Int[][] Edit=new int[m+1][n+1];
Prevent low-end cross-border and special case I for (int i=0;i<=m;i++) edit[i][0]=i;
for (int i=0;i<=n;i++) edit[0][i]=i;
for (int i=1;i<=m;i++) {for (int j=1;j<=n;j++) {///write J Here is a very common error if (j>i) edit[i][j]=edit[i][i]+j-i;
else if (j<i) edit[i][j]=edit[j][j]+i-j;
else {if (Str1.charat (i-1) ==str2.charat (j-1)) edit[i][j]=edit[i-1][j-1];
else edit[i][j]=edit[i-1][j-1]+1;
}}} return edit[m][n];
}//5. Determines whether the child sequence public static Boolean issubseq (String str1,string str2) {int pointer1=0;
int pointer2=0; while (Pointer1<str1.length () &&pointer2<str2.length ()) {if (Str1.charat (pointer1) ==str2.charat (
POINTER2)) pointer2++;
if (Pointer2==str2.length ()) return true;
pointer1++;
} return false;
public static void Main (string[] args) {//test program: Determines whether it is a substring.
System.out.println ("Abcsdf". Contains ("ABCD")); //test program: Determines whether it is a subsequence.
System.out.println (Issubseq ("ABSCDLJJKJKEFG", "ABCDEFG"));
Test program: Output the longest common subsequence length System.out.println (LCS ("ABSCLJJKJKEFG", "ABCDEFG"));
Test program: Output longest increment subsequence lis Nlogn int[] a={1,4,6,2,3,5,7};
System.out.println (LIS (a));
Test program: Output the longest increment subsequence LISDP n2 System.out.println (LISDP (a)); Test program: Output the longest common substring length System.out.println (lcstring ("ABSCLJJKJKDEFG", "ABCDEFG")); 3//Test program: Edit Distance System.out.println (Editdis ("Kitten", "sitting"));
3//int[] b={1,2,6};
System.out.println (BinarySearch (b,3));
}
}
If there is insufficient, but also hope that everyone pointed out ~