地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=17
单调递增最长子序列
时间限制:3000 ms | 内存限制:65535 KB
难度:4
-
描述
- 求一个字符串的最长递增子序列的长度
如:dabdbf最长递增子序列就是abdf,长度为4-
输入
- 第一行一个整数0<n<20,表示有n个字符串要处理
随后的n行,每行有一个字符串,该字符串的长度不会超过10000
输出 - 输出字符串的最长递增子序列的长度 样例输入
-
3 aaa ababc abklmncdefg
样例输出 -
1 3 7
- 第一行一个整数0<n<20,表示有n个字符串要处理
思路:就是分1个的时候,有多少个最长递增的,2个的时候,有多少个最长递增的,3个的时候,有多少个最长递增的,4个的时候,有多少个最长递增的......
用下列的方式进行存储,最长子序列的状态
public static void longestIncreasingSubsequenceDp2(String str){
char[] chs=str.toCharArray();
int length=chs.length;
int i,j,k,index;
int[] L=new int[length];
int[][] x=new int[length][length];
for(i=0;i<length;i++){
L[i]=1;
x[i][0]=chs[i]; //初始化,最长递增子序列长度为1
}
for(i=0;i<length;i++){
int max=1;
for(j=i-1;j>=0;j--){
if(chs[j]<chs[i]&&max<L[j]+1){
max=L[j]+1;
L[j]=max;
for(k=0;k<max-1;k++) //存储最长递增子序列
x[i][k]=x[j][k];
x[i][max-1]=chs[i]; //找到当前最长的子序列后,进行横向保存序列
}
}
}
for(index=0,i=1;i<length;i++) //找到最长的下标
if(L[index]<L[i])
index=i;
System.out.print("最长递增子序列是:");
for(i=0;i<L[index];i++)
System.out.println(x[index][i]+" ");
}
即:找到当前最长的,就进行横向保存序列。x[i][j],x[i][j+1],....
最后附上代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
while(n-->0){
String str=cin.next();
longestIncreasingSubsequenceDp1(str);
}
}
//253 371
public static void longestIncreasingSubsequenceDp1(String str){
char[] chs=str.toCharArray();
int length=chs.length;
int [] dp=new int[length];
for(int i=0;i<length;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(chs[j]<chs[i]&&dp[i]<dp[j]+1)
dp[i]=dp[j]+1;
}
}
int sum=0;
for(int i=0;i<length;i++){
if(dp[i]>sum)
sum=dp[i];
}
System.out.println(sum);
}
//保存了最长的子序列
public static void longestIncreasingSubsequenceDp2(String str){
char[] chs=str.toCharArray();
int length=chs.length;
int i,j,k,index;
int[] L=new int[length];
int[][] x=new int[length][length];
for(i=0;i<length;i++){
L[i]=1;
x[i][0]=chs[i]; //初始化,最长递增子序列长度为1
}
for(i=0;i<length;i++){
int max=1;
for(j=i-1;j>=0;j--){
if(chs[j]<chs[i]&&max<L[j]+1){
max=L[j]+1;
L[j]=max;
for(k=0;k<max-1;k++) //存储最长递增子序列
x[i][k]=x[j][k];
x[i][max-1]=chs[i]; //找到当前最长的子序列后,进行横向保存序列
}
}
}
for(index=0,i=1;i<length;i++) //找到最长的下标
if(L[index]<L[i])
index=i;
System.out.print("最长递增子序列是:");
for(i=0;i<L[index];i++)
System.out.println(x[index][i]+" ");
}
}