描述
求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4
-
输入
-
第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000
输出
- 输出字符串的最长递增子序列的长度 样例输入
-
3 aaa ababc abklmncdefg
样例输出
-
1 3 7
有两种方式可以求解,
解法一:
首先对字符串S1进行从小到大排序,然后删除有序数组相同的字符得到S2。再求S1与S2的最长子串即可(求子串的方法见两个字符串的最长相同子序列)。
排序方法:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public static char[] sort(char[] P,ref int m) 2 { 3 4 for (int j = 0; j < P.Length - 1; j++) 5 { 6 for (int i = 0; i < P.Length - 1 - j; i++) 7 { 8 if (P[i] > P[i + 1]) 9 { 10 char point1 = P[i]; 11 P[i] = P[i + 1]; 12 P[i + 1] = point1; 13 } 14 } 15 } 16 char x = P[1]; 17 int k = 2; 18 for (int i = 2; i < P.Length; i++) 19 { 20 if (P[i] != x) 21 { 22 P[k] = P[i]; 23 x = P[i]; 24 k++; 25 } 26 } 27 m = k; 28 return P; 29 }
解法二:
利用动态规划的思想,求S1[0...i]的最长递增子串,只需要比较S1[0...i-1]中S1[k]与S1[i]的大小。
f(i)=max(f(i-1),f(i-2),...,f(0))+1;用一个int dp[i]数组保存当前的f(i)值,即到第i个元素的最长递增子序列。
递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在i前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 public static int LongestAddSubsequence(string A) 2 { 3 int longest = 1; 4 int[] dp = new int[A.Length]; 5 for (int i = 0; i < A.Length; i++) 6 dp[i] = 1;//初始话均为1 7 for (int i = 1; i < A.Length; i++) 8 for (int j = i - 1; j >= 0; j--) 9 if (A[i] > A[j] && dp[i] < dp[j] + 1)//遇到比当前值小,并且长度比当前长度大的就更新当前长度 10 dp[i] = dp[j] + 1; 11 for (int i = 0; i < A.Length; i++) 12 if (dp[i] > longest) 13 longest = dp[i]; 14 return longest; 15 }