字符串的最大递增子串

来源:互联网 发布:智明创发软件待遇 编辑:程序博客网 时间:2024/06/06 09:20

字符串的最大递增子串

苏大   希望失望


问题

假设有一个字符串str,现求解出其长度最大的递增子串。

相关定义

子串:一个字符串substr是另一个字符串str的子串,需要满足两个条件:substr中的任一字符都在str中存在;substr中的字符在str中需要按序存在。例如,令str="aghkbdl",那么"akd"是其子串,而"adk"却不是其子串,因为在str中k在d的前面。

递增子串:首先是字符串的子串,其次需要满足子串中的字符是递增的。

问题分析

        假设有一字符串x1, x2,x3,...,xn。那么,该字符串的以任意字符开始且依次选择任意长度构成的串都是该字符串的子串。那么,我们首先应该想到的是“枚举法”即生成所有递增子串,然后遍历这些递增子串,从中选择出长度最大的。然后,其时间复杂度很高。具体求解代码可以参考问题求解节。

        我们知道,现存有很多算法设计思想,比如常用的就是枚举和回溯法。事实上上还有分治法和动规。分治法一般用于降低n^2复杂度。动规需要利用空间换时间。下面,我们来介绍如何利用动规求解该问题。

        要利用动态规划求解问题。需要做到三点:子问题的定义,子问题之间的递推关系,最小子问题。通常来子问题之间并不是独立的,这就使得动态规划一般不应该使用递归去设计。本文要解决的问题是求解字符串的最大递增子串。那么,我按以下步骤进行介绍。

      子问题的定义

      我们定义这样的dp。dp(i)表示字符串str(1,i)的最大递增子串的长度。那么,问题最终转换为求解str(1,len)的最大递增子串的长度。

      子问题之间的递推关系

      定义好了dp表示的含义之后。我们就需要找到各个子问题之间的关系。现在我们任取一个子问题str(i),那么,该问题的前驱子问题有哪些呢?前驱子问题就是str(i)能够再分解而得的子问题。对于str(i)而言,str(1),str(2),...,str(i-1)中任意字符都可能比str(i)小。假设str(j)比str(i)小,那么,str(i)的递增子串的长度应该为str(j)+1。由此分析可知,

dp(i)=max{ dp(j)+1| str[j]<str[i]}.

      可直接求解子问题

     显然可求解子问题为:当字符串为空时,dp()=0;第一个字符dp(1)=1。

     上面给出了子问题的定义,子问题之间的递推关系,可直接求解的子问题。那么,当这三者找到时,动态规划算法的求解代码就水到渠成了。具体惨照问题求解章节

问题求解

动态规划求解

#include <iostream>#include<vector>using namespace std;//在字符串中查找最长递int const MAXSIZE = 50;int GetMaxLength(char* str, int len){if (len <= 0)return 0;int* dp = new int[len];int maxl = 1;for (int i = 0; i <len; i++)dp[i] = 1;for (int i = 1; i < len; i++){for (int j = i - 1; j >= 0; j--)if (str[i]>str[j] && dp[i] < dp[j] + 1)dp[i] = dp[j]+1;if (dp[i] > maxl)maxl = dp[i];}delete[] dp;return maxl;}



阅读全文
0 0
原创粉丝点击