ny-单调递增最长子序列

来源:互联网 发布:万德软件科技有限公司 编辑:程序博客网 时间:2024/05/21 06:19

单调递增最长子序列

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述
求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4
输入
第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000
输出
输出字符串的最长递增子序列的长度
样例输入
3aaaababcabklmncdefg
样例输出
137
解题思路
先解释下什么叫子序列。若a序列删去其中若干个元素后与b序列完全相同,则称b是a的子序列。
我们假定存在一个单调序列{An}(以递增序列为例),现在在其后面添加一个元素a(n+1),有两种情况:1.a(n+1)>a(n)。此时,a(n+1)可以添加到An序列的尾部,形成一个新的单调序列,并且此序列长度大于之前An的长度;2.a(n+1)<=a(n)。此时,a(n+1)当然不可以添加到An序列的尾部。经过分析,我们可以得出这样的结论:一个单调序列与其后面元素的关系仅与此序列的末尾元素有关。如此,便有了此题如下的dp解法:建立一个一维数组dp[ ],用dp[i]保存长度为i的单调子序列的末尾元素的值,用top保存单调子序列的最大长度。初始top=1,dp[1]=a1;然后,我们从前向后遍历序列An(i : 2~n)。显然,我们会遇到两种情况:1.a[i] > dp[top]。此时,我们把a[i]加入到长度为top的单调序列中,这时序列长度为top+1,top值也跟着更新,即dp[++top] = a[i];2.a[i]<=dp[top]。此时,a[i]不能加入长度为top的单调序列,那它应该加入长度为多少的序列呢?做法是,从前向后遍历dp[ ] (j: 1~top-1),直到满足条件 a[i] > dp[j],此时,我们将dp[j]的值更新为a[i]。可是,为什么要更新它呢?因为对于相同长度的单调递增序列来说,末尾元素的值越小,其后元素加入此序列的可能性越大,也就是说,我们这样做,是为了防止丢失最优解。
例:
s abclmndefgdp abclmn   abcdmn   abcden   ...   abcdefg
代码
#include<stdio.h>#include<string.h>char s[11000],dp[11000];int main(){int n;int len;int i,j,k;int max;scanf("%d",&n);while(n--){scanf("%s",s);len=strlen(s);memset(dp,0,sizeof(dp));dp[1]=s[0];max=1;for(i=1;i<len;i++){if(s[i]>dp[max])    dp[++max]=s[i];else{for(j=1;s[i]>dp[j];j++){}dp[j]=s[i];}}printf("%d\n",max);}return 0;}


0 0
原创粉丝点击