【问题描述】输入一行字符串,该字符串只由小写英文字母a-z组成,且其中的字符可以重复,最长不超过10000个字符。
从该字符串中按顺序挑选出若干字符(不一定相邻)组成一个新串,称为“子串”。如果子串中每两个相邻的字符或者相等,或者后一个比前一个大,则称为“升序子串”。编程求出输入字符串的最长升序子串的长度。
例如,由输入字符串abdbch可以构成的升序子串有:abd、abch、bbch、abbch等。其中最长的升序子串是abbch,其长度为5。
【输入形式】从标准输入读取一行字符串,该串不含空格,以回车符结束。
【输出形式】向标准输出打印一个正整数,是字符串中最长的升序子串的长度,在行末要输出一个回车符。
【输入样例】abdbch
【输出样例】5
【样例说明】abdbch中最长子串是abbch,长度是5。
该题是动态规划题
abdbch
以seq[0]='a' 为结尾的最长子串长度为1
以seq[1]='b' 为结尾的最长子串长度为2
以seq[2]='d' 为结尾的最长子串长度为3
以seq[3]='b' 为结尾的最长子串长度为3
以seq[4]='c' 为结尾的最长子串长度为4
以seq[5]='h' 为结尾的最长子串长度为5
状态转移方程:
if max{resultLen[j] | seq[i]>=seq[j]| 0<=j<i } 不为空集 resultLen[i]= max{resultLen[j] | seq[i]>=seq[j]| 0<=j<i } + 1
else resultLen[i]=1
resultLen[0]=1,
resultLen[1]: 对应的字符是b,b肯定能接在a后面 =>resultLen[1]=resultLen[0]+1=2。
resultLen[2]: resultLen[2]=max{resultLen[0],resultLen[1]} + 1 = 3
resultLen[3]: resultLen[3]= max{resultLen[0],resultLen[1]} + 1 = 3
resultLen[4]: resultLen[4] = max{resultLen[0],resultLen[1],resultLen[3]} + 1 = 4
resultLen[5]: resultLen[5] = max{resultLen[0],resultLen[1],resultLen[2],resultLen[3],resultLen[4]} + 1 = 5
#include<iostream> #include<vector> #include<algorithm> #include<string> #include<stdio.h> using namespace std; #define N 26 #define maxLen 10000 string LestIncSubStr(string seq){ int resultLen[maxLen]; //resultLen[i]表示以第i+1个输入字符为结尾的最长升序子列 string resultSeq = ""; resultLen[0] = 1;//很明显以第一个输入字符为结尾的最长升序子列的长度为1 for (int i = 1; i < seq.length(); ++i){ //每次循环算出一个resultLen resultLen[i] = 1; for (int j = 0; j < i; ++j){ //遍历之前已经算出的resultLen数组 if (seq[i] >= seq[j] && resultLen[i] < resultLen[j] + 1){ resultLen[i] = resultLen[j] + 1; } } } int len = *(std::max_element(&resultLen[0], &resultLen[seq.length()])); //对于数组int array[length],开始位置为&array[0],结束位置是&array[length],&array[length]为最后一个元素的后一个位置,与迭代器的iterator.end()是一个作用 cout << "最长升序子列的长度为:" << len << endl; //计算子序列的具体内容 int index; for (int i = 0; i < seq.length(); ++i){ if (resultLen[i] == len){ //找到以seq[index]为结尾的最长子序列 index = i; resultSeq.push_back(seq[i]);//将子序列的最后一个字符加入 } } while (len != 1 ){ for (int j = 0; j < seq.length(); ++j){ if (seq[index] >= seq[j] && len == resultLen[j] + 1){//当 len--; index = j; resultSeq.insert(resultSeq.begin(), seq[j]); } } } cout << "最长子序列为:" << resultSeq; return ""; } int main(){ string seq; cin >> seq; LestIncSubStr(seq); system("pause"); return 0; }