最长升序子串(动态规划)

 【问题描述】输入一行字符串,该字符串只由小写英文字母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;
}

 

posted on 2017-04-04 14:59  codeDog123  阅读(1521)  评论(0编辑  收藏  举报

导航