题目描述
![](https://img-blog.csdnimg.cn/img_convert/8d7246658cb94fccb532dcaa37702793.png)
输入描述
第一行为第一个字符序列,都是大写字母组成,以 . 结束。长度小于 5000。
第二行为第二个字符序列,都是大写字母组成,以 . 结束,长度小于 5000。
输出描述
第一行输出上述两个最长公共子序列的长度。
第二行输出所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对 1×1081×108 求余即可。
输入输出样例
示例 1
输入
ABCBDAB.
BACBBD.
输出
4
7
运行限制
最大运行时间:1s
最大运行内存: 128M
源码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class 最长公共子序列_困难 {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String s1=br.readLine();
s1=s1.substring(0,s1.length()-1);
String s2=br.readLine();
s2=s2.substring(0,s2.length()-1);
int mod=(int)1e8;
int[][] dp = new int[2][s2.length()+1]; //记录最长公共子序列
int[][] cnt = new int[2][s2.length()+1]; //记录最长公共子序列的方案数
int n=s1.length();
int m=s2.length();
//进行cnt的初始化,某个字符取前0个元素的时候
for (int i = 0; i < m+1; i++) {
cnt[0][i]=1;
}
cnt[1][0]=1;
for (int i = 1; i <= n; i++) {
int now=i&1;
int pre=now^1;
for (int j = 1; j <= m; j++) {
dp[now][j]=Math.max(dp[now][j-1], dp[pre][j]);
cnt[now][j]=0; //当前状态是由上一个状态转移过来的!!!
if (s1.charAt(i-1) == s2.charAt(j-1)) {
dp[now][j]=Math.max(dp[now][j], dp[pre][j-1]+1);
if (dp[now][j]==dp[pre][j-1]+1) {
cnt[now][j]+=cnt[pre][j-1] % mod;
}
}else {
//删去重复添加方案
if (dp[now][j]==dp[pre][j-1]) {
cnt[now][j]-=cnt[pre][j-1];
}
}
if (dp[now][j]==dp[pre][j]) {
cnt[now][j]+=cnt[pre][j]%mod;
}
if(dp[now][j]==dp[now][j-1]) {
cnt[now][j]+=cnt[now][j-1]%mod;
}
}
}
System.out.println(dp[n&1][m]);
System.out.println(cnt[n&1][m]);
}
}