Reference: http://www.ahathinking.com/archives/124.html
Longest common sub-sequence
1. Dynamic Planning and solving process
1) Describe one of the longest common sub-sequences
If the sequence is shorter, the brute force method can be used to enumerate all the sub-sequences of X, and then check if it is a subsequence of Y and record the oldest sequence found. If the sequence is longer, this method requires a number of times, which is impractical.
the optimal substructure theorem for LCS : Set X={X1,X2,......,XM} and Y={y1,y2,......,yn} to two sequences, and set Z={Z1, Z2 、......, ZK} to any LCS of X and Y:
(1) If Xm=yn, then Zk=xm=yn, and Zk-1 is an LCS of Xm-1 and Yn-1.
(2) If Xm≠yn, then ZK≠XM implication Z is an LCS of Xm-1 and yn.
(3) If Xm≠yn, then Zk≠yn implication Z is an LCS of XM and Yn-1.
The theorem illustrates that an LCS of two sequences also contains a two-sequence prefix for an LCS, i.e. the LCS problem has the optimal substructure properties.
2) A recursive solution
According to the sub-structure of the LCS, to find the sequence x and Y LCS, based on whether XM and yn are equal to judge, if the Xm=yn is a sub-problem, otherwise, two sub-problems arise. Set C[I,J] is the length of an LCS for sequence XI and YJ. If I=0 or j=0, that is, the length of a sequence is 0, the length of the LCS is 0. The recursive formula for the optimal substructure of the LCS problem is as follows:
Implementation algorithm:
voidlcs_length () {inti,j; for(i=1; i<=x_len;i++) c[i][0]=0; for(i=0; i<=y_len;i++) c[0][i]=0; for(i=1; i<=x_len;i++) for(j=1; j<=y_len;j++) { if(s1[i-1]==s2[j-1]) {C[i][j]=c[i-1][j-1]+1; B[I][J]='\\'; } Else if(c[i-1][j]>=c[i][j-1]) {C[i][j]=c[i-1][j]; B[I][J]='|'; } Else{C[i][j]=c[i][j-1]; B[I][J]='-'; } }}
The longest common child string
A classic problem with dynamic programming is the longest common subsequence, but the sub-sequences here do not require continuous, and if the requirement sequence is continuous, we call the common substring, so how do we get this string?
The simplest method is to compare, in turn, a string as a string, and then generate another string of all the length of the substring, in turn, to compare the search in the string, which can be used first from the longest substring start, reduce the number of comparisons, but the complexity is still very high!
Then look at the problem again, we build a comparison matrix to compare two strings of str1 and str2
Define LCS (I,J) when str1[i] = Str2[j] LCS (I,J) = 1, otherwise equal to 0.
Example
str1 = "Bab"
str2 = "Caba"
Build a matrix
--b a B
C 0 0 0
A 0 1 0
B 1 0 1
A 0 1 0
The feature of the continuous I substring is that if str1[i] and Str2[j] are the last characters belonging to a common substring, then there must be Str1[i]=str2[j] && str1[i-1] = Str2[j-1], which is intuitively seen from The matrix, which is the " The 1 "Slash" represents the sequence of common substrings , then the longest common substring must be the longest string of the slash "1" .
So now the problem can be transformed, as long as the construction of a matrix, with n^2 time to get the matrix, and then to the matrix to find the longest "1" of the formation of the slash can be ! So, now there's a new problem? How to quickly find the "1" made up of the longest slash it?
Using DP's idea, if str1[i] = Str2[j], then the length of the common substring containing str1[i] and str2[j] is necessarily the length of the common substring containing str1[i-1] and str2[j-1] plus 1, so now we can redefine the LCS ( I,J), which is LCS (i,j) = LCS (i-1,j-1) + 1, and vice versa, LCS (i,j) = 0. Then the matrix above becomes the following:
--b a B
C 0 0 0
A 0 1 0
B 1 0 2
A 0 2 0
Now the problem has become simpler, only need to spend n^2 time to construct such a matrix, and then spend n^2 time to find the largest value in the matrix, corresponding to the length of the longest common substring, and the maximum corresponding to the position of the corresponding character, is the longest common substring of the last character .
The algorithm can also be improved, we can find the maximum length and the work of the corresponding characters in the construction of the Matrix, while the construction side of the record current maximum length and corresponding position, so that the n^2 to save time to find .
Implementation algorithm:
/*Maximum common string DP*/intdp[ -][ -]; voidLCS_DP (CharXintXlen,CharYintYlen) {MaxLen= Maxindex =0; for(inti =0; i < Xlen; ++i) { for(intj =0; J < Ylen; ++j) {if(X[i] = =Y[j]) { if(I &&j)//i and J are not at 0 when {Dp[i][j]= dp[i-1][j-1] +1; } if(i = =0|| j = =0) {Dp[i][j]=1; } if(Dp[i][j] >maxlen) {MaxLen=dp[i][j];//Longest substring length maxindex= i +1-maxlen;//Find out where the common substring started}} }} Outputlcs (X);}
Longest repeating substring maximum non-repeating substring
From the second character to join the non-repeating substring, if there is a duplicate character in the existing non-repeating string, then this character cannot join, at this point, you need to calculate the maximum non-repeating length, and then update the first subscript of the non-repeating string to the next one of the repeating characters.
intLengthoflongestsubstring (strings) {if(S.empty ())return 0; intmaxlen=1; inti,j,k; J=0; K=0; for(i=1; i< (int) S.size (); i++) {J=K; while(j<i) {if(s[i]!=S[j]) J++; Else { if(i-k>maxlen) MaxLen=i-K; K=j+1; Break; } } } if(i-k>maxlen) MaxLen=i-K; returnMaxLen; }
Longest palindrome substring
This can be accomplished using dynamic planning, Leetcode on the topic.
stringLongestpalindrome (strings) {if(S.empty ())returnNULL; intstart=0; intEnd=0; intn=s.length (); BOOLDp[n][n]; Memset (DP,false,sizeof(DP)); inti; dp[0][0]=true; for(i=1; i<n;i++) {Dp[i][i]=true; Dp[i][i-1]=true; } intK//K is used to record the length of the substring starting from I, when the length is 1 is definitely a palindrome, judging from the len=2 start for(k=2; k<=n;k++) { for(i=0; i<=n-k;i++) { if(s[i]==s[i+k-1]&&dp[i+1][i+k-2]) {dp[i][i+k-1]=true; if(k>end-start+1) {Start=i; End=i+k-1; } } } } returnS.substr (start,end-start+1); }
Maximum Increment sub-sequence
Method One: DP
As with LCS, it is easy to think that the length of the longest increment subsequence before the element i is either 1 (in a single sequence) or the longest increment sub-sequence preceding the i-1 element plus 1, which can have a state equation:
Lis[i] = max{1,lis[k]+1}, wherein, for arbitrary k<=i-1,arr[i] > Arr[k], so that arr[i] in order to form a new increment sub-sequence on the basis of arr[k.
intLIS (intArr[],intN) { int*dp=New int[n]; for(intI=0; i<n;i++) {Dp[i]=1; for(intj=0; j<i;j++) { if(arr[i]>arr[j]&&dp[i]<dp[j]+1) Dp[i]=dp[j]+1; }
}}
Maximum Subarray and (contiguous subarray Max and)
There may be two cases, one of which is to return 0 or the smallest negative number in the array if and all negative numbers? Is whether the elements of the array must be selected or not selected. You can see http://blog.csdn.net/v_july_v/article/details/6444021.
If the elements in the array are not to be selected, implement the code:
intMaxsubarray (intA[],intN) {if(n==0) return 0; intmaxsum=a[0]; intsum=a[0]; inti; for(i=1; i<n;i++) { if(sum<0) Sum=A[i]; Elsesum+=A[i]; if(maxsum<sum) {Maxsum=sum; } } returnmaxsum; }
Otherwise, sum and maxsum=0 can be made.
Longest common subsequence | longest common substring | longest repeating substring | Longest non-repeating substring | longest palindrome | longest incrementing subsequence | maximum Subarray and