输出所有的最长单调递增子序列。

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();
	}
}

结果如下:














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值