package dp;
import java.lang.*;
import java.util.*;
/**
* **
* @author lcq
*
* 最长单调递增子序列
* 对于字符串s,用数组l记录长度,l[i]表示以s.charAt(i)结尾的最长单调递增子序列的长度。初始化为1.
* l[i] = max(l[i],l[j]+1),其中j满足0<=j<i且s.charAt(j) < s.charAt(i).
*/
public class LIS {
public LIS(String s)
{
this.s = s;
l = new int[s.length()];
for(int i=0;i<l.length;++i)
l[i] = 1;
solve();
}
public void display()
{
int maxIndex = maxIndex(l,0,l.length);//数组l中最大值的下标。
int length = l[maxIndex];//最大长度。
System.out.println("The length of LIS of "+s+" is "+length);
StringBuilder sb = new StringBuilder();//用于记录LIS。
while(length != 0)
{
sb.append(s.charAt(maxIndex));
--length;
//查找0到maxIndex,在l中长度为length,且对应的s中的字符要比刚刚记录到sb中的字符小的下标。
for(int i=0;i<maxIndex;++i)
if(l[i] == length && s.charAt(i) < s.charAt(maxIndex))
{
maxIndex = i;
break;
}
}
sb.reverse();
System.out.println(sb.toString());
}
public void displayAll()
{
//记录下标
Stack stack = new Stack();
//记录LIS的字符。
StringBuilder sb = new StringBuilder();
//最大长度。
int length = l[maxIndex(l,0,l.length)];
//将长度为length的所有下标入栈。
for(int i=0;i<l.length;++i)
if(l[i] == length)
stack.push(i);
while(!stack.empty())
{
int maxIndex = (int)stack.pop();//对栈顶下标进行处理。
length = l[maxIndex];
//寻找LIS的同时,用栈stack记录l中具有相同长度的的下标位置。
while(length != 0)
{
sb.append(s.charAt(maxIndex));
--length;
if(length != 0)
{
for(int i=0;i<maxIndex;++i)
if(l[i] == length && s.charAt(i)<s.charAt(maxIndex))
stack.push(i);
maxIndex = (int)stack.pop();
}
}
//输出一个LIS
sb.reverse();
System.out.println(sb.toString());
sb.reverse();
//回退。
if(!stack.empty())
{
//若当前栈顶对应的长度为k,则sb需回退k次,即需删除sb中的k个元素。
for(int i=1;i<=l[(int)stack.peek()];++i)
sb.deleteCharAt(sb.length()-1);
}
}
}
//返回数组array中[begin,end)之间的最大值的下标。
private static int maxIndex(int[] array,int begin,int end)
{
int max = begin;
for(int i=begin+1;i<end;++i)
if(array[max] < array[i])
max = i;
return max;
}
//求解数组l。
private void solve()
{
for(int i=1;i<s.length();++i)
for(int j=0;j<i;++j)
if(s.charAt(i) > s.charAt(j))
l[i] = Math.max(l[i], l[j]+1);
}
private String s;
private int[] l;
}
public class FirstSample
{
public static void main(String[] args)
{
String s = "ACBDECD";
LIS lis = new LIS(s);
lis.displayAll();
}
}
结果如下: