单调递增最长子序列
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4-
输入
-
第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000
输出
- 输出字符串的最长递增子序列的长度 样例输入
-
3 aaa ababc abklmncdefg
样例输出
-
1 3 7
来源
- 经典题目 上传者
求单调递增最长子序列(Longest Increasing Subsequence),LCS
对于这个问题,我想我的思路是比较简单的用动态规划来解。
只是另外开了一个数组,用来存放字符串中当前字符所能组成的最大上升子序列的长度,最后把长度最大的数输出来就是单调递增子序列的最大长度。
从网上找来了一个较为详细的解释,思路是和我的一样,不过我表达能力不是太强,就借鉴一下别人的
(作者的解释:)令A[i]表示输入第i个元素,D[i]表示从A[1]到A[i]中以A[i]结尾的最长子序列长度。对于任意的0 < j <= i-1,如果A(j) < A(i),则A(i)可以接在A(j)后面形成一个以A(i)结尾的新的最长上升子序列。对于所有的 0 < j <= i-1,我们需要找出其中的最大值。DP状态转移方程:D[i] = max{1, D[j] + 1} (j = 1, 2, 3, ..., i-1 且 A[j] < A[i])解释一下这个方程,i, j在范围内:如果 A[j] < A[i] ,则D[i] = D[j] + 1如果 A[j] >= A[i] ,则D[i] = 1
下面是我的代码:
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; int main() { int t,i,j,len; char a[10005]; int b[10005];//长度 cin>>t; while(t--) { cin>>a; int sum=1,max; len=strlen(a); for(i=0;i<len;i++) b[i]=0; for(i=0;i<len;i++) { max=0; for(j=0; j<=i; j++) { if(a[j]<a[i])//找到比当前字符小的字符并且其长度最大的 { if(max<b[j]) max=b[j]; } } b[i]=max+1; } sort(b,b+len); cout<<b[len-1]<<endl; } return 0; }
借鉴来的代码:
我还找到了一个可以优化为nlogn的算法,有需要可以看看,另附加一个最长公共子序列代码#include<iostream> #define SIZE 1001 using namespace std; int main() { int i, j, n, max; /* a[i]表示输入第i个元素 */ int a[SIZE]; /* d[i]表示以a[i]结尾的最长子序列长度 */ int d[SIZE]; while(cin >> n) { for (i = 1; i <= n; i++) { cin >> a[i]; } max = 0; for (i = 1; i <= n; i++) { d[i] = 1; for (j = 1; j <= i - 1; j++) { if (a[j] < a[i] && d[i] < d[j] + 1) //这边,要注意 d[i] < d[j] + 1这个条件的限制,它是为了在 //连续几个 d[i]相同时 只加一次 { d[i] = d[j] + 1; } } /* 记录最长子序列 */ if (d[i] > max) max = d[i]; } cout << max << endl; } //system("pause"); return 0; }
-
第一行一个整数0<n<20,表示有n个字符串要处理