找到非递减子序列是众所周知的问题。 但是这个问题是发现最长的非递减子序列的一个轻微变体。在这个问题中,我们必须找到包含2个不相交序列的最长子序列的长度 1.非减少2.非增加。 例如在字符串“aabcazcczba”中最长的序列是aabczcczba。 aabczcczba由2个不相交的子序列aabcZccZBA组成。 (大写字母显示非递增序列)
我的算法是
length = 0
For i = 0 to length of given string S
let s' = find the longest non-decreasing subsequence starting at position i
let s" = find the longest non-increasing subsequence from S-s'.
if (length of s' + length of s") > length
length = (length of s' + length of s")
enter code here
但我不确定这是否能给出正确答案。你能在这个算法中找到一个错误吗?如果有错误也提示正确的算法。我还需要优化解决方案。我的算法大概需要o(n ^ 4)步。
答案 0 :(得分:1)
您的解决方案绝对不正确。例如。 addddbc。最长的非递减序列是adddd,但是这永远不会给你一个不增加的序列。最佳解决方案是abc和dddd(或ab ddddc或ac ddddb)。
一种解决方案是使用动态编程。
F(i,x,a,b)= 1,如果x(x [:i])的前i个字母存在非递减和非递增的组合,则非递减部分的最后一个字母是a,非增加部分是b。如果相应的子序列为空,则这两个字母都等于NULL。
否则F(i,x,a,b)= 0。
F(i+1,x,x[i+1],b) = 1 if there exists a and b such that
a<=x[i+1] or a=NULL and F(i,x,a,b)=1. 0 otherwise.
F(i+1,x,a,x[i+1]) = 1 if there exists a and b such that
b>=x[i+1] or b=NULL and F(i,x,a,b)=1. 0 otherwise.
Initialize F(0,x,NULL,NULL)=1 and iterate from i=1..n
如您所见,您可以从F(i,x,a,b)得到F(i + 1,x,a,b)。复杂性:长度为线性,字母表大小为多项式。
答案 1 :(得分:0)
我得到了答案,这就是它的工作方式,而不是@ElKamina
维护一个27X27维度的表格。 27 =(1个空字符+ 26个(字母)) table [i] [j]表示子序列的长度,其非递减子序列具有最后一个字符'i',而非递增子序列具有最后一个字符'j'(第0个索引表示空字符,第k个索引表示字符'k')< / p>
表示i = 0到字符串S的长度
//subsequence whose non decreasing subsequence's last character is smaller than S[i], find such a subsequence of maximum length. Now S[i] can be part of this subsequence's non-decreasing part.
int lim = S[i] - 'a' + 1;
for(int k=0; k<27; k++){
if(lim == k) continue;
int tmax = 0;
for(int j=0; j<=lim; j++){
if(table[k][j] > tmax) tmax = table[k][j];
}
if(k == 0 && tmax == 0) table[0][lim] = 1;
else if (tmax != 0) table[k][lim] = tmax + 1;
}
//Simillarly for non-increasing subsequence
时间复杂度为o(lengthOf(S)* 27 * 27),空间复杂度为o(27 * 27)