最长递增子序列的长度
- 【描述】
- 求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4
- 【输入】
- 第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000 - 【输出】
- 输出字符串的最长递增子序列的长度
方法一:
==========================================
用一个数组保存以当前字符作为结束的最长字串
对于一个字符串 s ,申请同样长度的数组 X,X[i] 表示以s[i]结束的最长单调递增子串
X[i] = max{ X[j]+1 } ,其中0≤j<i,且s[j]<s[i]
则s的最长升序子串为 max{ X[i] }
复杂度O(N^2)
#include<iostream> #include<string> using namespace std; int main(){ int N; cin >> N; string s; while(N--){ cin >> s; int* x = new int[s.length()]; for (unsigned int i=0;i<s.length();i++) x[i] = 1; int max = 1; for(unsigned int i=1;i<s.length();i++){ for(int j=i-1;j>=0;j--) { if(s[j]<s[i]){ if(x[j]+1>x[i]){ x[i] = x[j]+1; } } } if(max<x[i]) max = x[i]; } cout << max << endl; } return 0; }
方法二:
==========================================
用一数组保存最长长度为下标的最小字符。
#include<iostream> #include <string> using namespace std; int main() { 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; } return 0; }
方法三:
=======================================================
如果字符的范围有限,那么可以有O(N)时间的算法。
设串的字符集为S,包含N个元素,每个元素为Ak,Ai < Aj (0 <= i < j < N)。
设串T中以Ap结尾的单调递增子序列长度为len(T, Ap),则T的单调递增子序列长度为Maxlen(T) = max(len(T,A0), len(T, A1), ..., len(T,An-1))。
如果给串T的末尾再添加一个字符Aq,则len(T + Aq, Aq) = len(T, Aq - 1) + 1。
#include<stdio.h> int length(char * s) { int len[128] = {0}, i, t; for(; *s != '\0' ; s++){ t = len[*s - 1] + 1; for(i = *s; i < 128 && len[i] < t; i++) len[i] = t; } return len[127]; } int main() { int n; char s[10001]; for(scanf("%d\n", &n); n--;) printf("%d\n", length(gets(s))); return 0; }