求子序列:(输出字符串长度)
int len1, len2;
const int n = 1002;
int b[n][n];//b[i][j]表示c[i][j]的来源,用于输出最长公共子序列 为1时说明s1[i-1]=s2[j-1] 则可以递归函数print再输出s1[i-1]
//b[i][j]为2时说明s1[i-1]不等于s2[j-1] 最优解来源于c[i][j]=c[i][j-1] 递归输出print(i,j-1)
//为3时说明1[i-1]不等于s2[j-1] 最优解来源于c[i][j]=c[i-1][j] 递归输出print(i-1,j) i或者j为0时递归结束
int c[n][n];//c[len1][len2]表示最长公共子序列的长度
char s1[n], s2[n];
void LCSL() {
for (int i = 1; i <= len1; i++)
for (int j = 1; j <= len2; j++) {
if (s1[i - 1] == s2[j - 1]) {
b[i][j] = 1;
c[i][j] = c[i - 1][j - 1] + 1;
}
else if (c[i - 1][j] >= c[i][j - 1]) {
b[i][j] = 2;
c[i][j] = c[i - 1][j];
}
else {
b[i][j] = 3;
c[i][j] = c[i][j - 1];
}
}
}
void print(int i, int j) {
if (i == 0 || j == 0) return;
if (b[i][j] == 1)
{
print(i - 1, j - 1);
cout << s1[i - 1];
}
else if (b[i][j] == 2) {
print(i - 1, j);
}
else
print(i, j - 1);
}
int main()
{
cout << "input s1 and s2";
cin >> s1;
cout << "s2:";
cin >> s2;
len1 = strlen(s1);
len2 = strlen(s2);
for (int i = 0; i < len1; i++) {
for (int j = 0; j < len2; j++) {
c[0][j] = 0;
c[i][0] = 0;
}
}
LCSL();
print(len1, len2);
}
求长度:
public static int getLCS(char[] x, char[] y) {
// base case,默认 dp 中的每个元素都为 0。定义dp[i][j]表示字符串str1中第i个字符和str2种第j个字符为最后一个元素所构成的最长公共子串
int dp[][] = new int[x.length+1][y.length+1];
// 最长公共子串, 用一个临时变量表示
int resultLCS = 0;
for (int i = 1; i <= x.length; i++) {
for (int j = 1; j <= y.length; j++) {
// 以下是状态转移方程
if (x[i-1] == y[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
resultLCS = Math.max(resultLCS, dp[i][j]);
} else {
dp[i][j] = 0;
}
}
}
return resultLCS;
}
求最长公共子串:若有多个,输出在较短串中最先出现的那个。
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
String str1=in.nextLine();
String str2=in.nextLine();
String ans="";
String temp="";
// 保证str1是较短字符串
if (str1.length() > str2.length()) {
temp = str1;
str1 = str2;
str2 = temp;
}
int m = str1.length() + 1;
int n = str2.length() + 1;
// 表示在较短字符串str1以第i个字符结尾,str2中以第j个字符结尾时的公共子串长度。
int[][] dp = new int[m][n];
// 匹配字符,并记录最大值的str1的结尾下标
int max = 0;
int index = 0;
// 从左向右递推,i为短字符串str1的结尾索引,j为str2的结尾索引
for (int i=1; i < m; i++) {
for (int j=1; j < n; j++) {
if (str1.charAt(i-1) == str2.charAt(j-1)) {
// 相等则计数
dp[i][j] = dp[i-1][j-1] + 1;
// 不断更新变量
if (dp[i][j] > max) {
max = dp[i][j];
index = i;
}
}
}
}
// 截取最大公共子串
System.out.println(str1.substring(index-max, index));
}