nyist oj 17 单调递增最长子序列 (动态规划经典题)
单调递增最长子序列
时间限制:3000 ms | 内存限制:65535 KB
难度:4
- 描述
- 求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4- 输入
- 第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000 - 输出
- 输出字符串的最长递增子序列的长度
- 样例输入
-
3 aaa ababc abklmncdefg
- 样例输出
-
1 3 7
- 来源
动态规划的经典题目;好像还有好几种解法,我现在研究的是最基础的解法;
这里直接参考了 http://blog.****.net/sjf0115/article/details/8715672 的博客,把其中的图片复制过来了,感觉讲的还不错,加深对这类题目的理解;
http://www.cnblogs.com/mycapple/archive/2012/08/22/2651453.html 这篇博客讲的也不错
- #include <cstdio>
- #include <cstring>
- const int maxn=10001;
- char s[maxn];
- int dp[maxn],Max;
- void LICS()
- {
- int len;
- memset(dp,0,sizeof(dp));
- len=strlen(s);
- for(int i=0;i<len;i++)
- {
- dp[i]=1;//给定一个数组求的时候,初始值就是1,一个数组的最大序列肯定会有一个字符;
- for(int j=0;j<i;j++)
- {
- if(s[i]>s[j] && dp[i]<1+dp[j])// 递推公式,如果这个位置比前面的字符都大,就加入到递增序列中来
- dp[i]=1+dp[j];
- }
- }
- Max=0;
- for(int i=0;i<len;i++)//求出最大值
- if(Max<dp[i])
- Max=dp[i];
- }
- int main()
- {
- int t;
- scanf("%d",&t);
- while(t--)
- {
- scanf("%s",s);
- LICS();
- printf("%d\n",Max);
- }
- return 0;
- }
看到了这道题的最优代码;上面我写的提交300多ms,最优代码只要4ms,0ms也许也可以达到;但是有点看不懂的节奏啊,保存学习一下;
- #include<iostream>
- #include <string>
- //#include <time.h>
- using namespace std;
- int main()
- {
- //freopen("1.txt","r",stdin);
- int n ;
- cin>>n;
- while(n--)
- {
- string str;
- int count=1;
- cin>>str;
- int a[200];
- a[0]=-999;
- for (int i=0;i<str.length();i++)
- {
- for (int j=count-1;j>=0;j--)
- {
- if((int)str[i]>a[j])
- {
- a[j+1]=str[i];
- if(j+1==count) count++;
- break;
- }
- }
- }
- cout<<count-1<<endl;
- }
- //cout<<(double)clock()/CLOCKS_PER_SEC<<endl;
- return 0;
- }