您的位置:首页 > 其它

NYOJ17 单调递增最长子序列(最长单调递增子序列)

2016-11-23 19:25 351 查看
题目:

单调递增最长子序列

时间限制:3000 ms  |  内存限制:65535 KB难度:4描述求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4输入第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000输出输出字符串的最长递增子序列的长度样例输入
3
aaa
ababc
abklmncdefg
样例输出
1
3
7
来源经典题目上传者iphxer
代码1:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int main()
{
int n;
char str[10005];//存储字符串
int num[10005];//当前元素作为最大元素的最长递增序列
scanf("%d",&n);
while(n--)
{
mem(str,'\0');
mem(num,0);//初始化str和num
int sum=0;
num[0]=1;//第一个元素的最长递增序列一定为1
scanf("%s",str);
int len=strlen(str);

for(int i=1; i<len; i++)
{
int flag=0;//代表num[i]的值
for(int j=0; j<i; j++)
{
if(str[i]>str[j]&&flag<num[j])//把当前的第i个元素和前面的每一个元素比较&&递增序列必须连续递增
{
flag=num[j];//更新序列长度
}
}
num[i]=flag+1;
}
for(int i=0; i<len; i++)
{
sum=max(sum,num[i]);//找出里面最大的长度
}
printf("%d\n",sum);
}
return 0;
}

把上面的代码优化一下,可以用逆推的方式这么写
代码2:
#include<stdio.h>
#include<string.h>
int dp[10010];
fc17

char a[10010];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
int i,la,j,maxn=-1;
scanf("%s",a+1);
la=strlen(a+1);
for(i=1;i<=la;i++)
{
for(j=i-1;j>=0;j--)
{
if(a[j]<a[i]&&dp[i]<dp[j]+1)//判断是否递增,并且判断当前元素所处递增序列的长度
dp[i]=dp[j]+1;//更新递增序列的最大长度
}
if(dp[i]>maxn)
maxn=dp[i];
}
printf("%d\n",maxn);
}
return 0;
}

关于这个问题有一篇博客写的很好:-->最长递增子序列详解(longest increasing subsequence)以下内容摘自上述博客
-----------------------------------------------------------------关于单调递增子序列--------------------------------------------------------------------------------
对于动态规划问题,往往存在递推解决方法,这个问题也不例外。要求长度为i的序列的Ai{a1,a2,……,ai}最长递增子序列,需要先求出序列Ai-1{a1,a2,……,ai-1}中以各元素(a1,a2,……,ai-1)作为最大元素的最长递增序列,然后把所有这些递增序列与ai比较,如果某个长度为m序列的末尾元素aj(j<i)比ai要小,则将元素ai加入这个递增子序列,得到一个新的长度为m+1的新序列,否则其长度不变,将处理后的所有i个序列的长度进行比较,其中最长的序列就是所求的最长递增子序列。举例说明,对于序列A{35, 36, 39, 3, 15, 27, 6, 42}当处理到第六个元素(27)时,以35, 36, 39, 3, 15, 27, 6为最末元素的最长递增序列分别为
    35
    35,36
    35,36,39
    3
    3,15
    3,15,27
    3,6
当新加入第10个元素42时,这些序列变为
    35,42
    35,36,42
    35,36,39,42,
    3,42
    3,15,42
    3,15,27,42
    3,6,42
这其中最长的递增序列为(35,36,39,42)和(3,15,27,42),所以序列A的最长递增子序列的长度为4,同时在A中长度为4的递增子序列不止一个。该算法的思想十分简单,如果要得出Ai序列的最长递增子序列,就需要计算出Ai-1的所有元素作为最大元素的最长递增序列,依次递推Ai-2,Ai-3,……,将此过程倒过来,即可得到递推算法,依次推出A1,A2,……,直到推出Ai为止2018年3月31日20:06:37重写O(N^2)#include <bits/stdc++.h>
using namespace std;
int dp[10000+100];
int main()
{
int t;
cin>>t;
while(t--)
{
int maxx=0;
string s;
cin>>s;
int len=s.length();
for(int i=0; i<len; i++)
{
dp[i]=1;
for(int j=0; j<i; j++)
{
if(s[j]<s[i]&&dp[j]+1>dp[i])
{
dp[i]=dp[j]+1;
}
}
maxx=max(maxx,dp[i]);
}
cout<<maxx<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: