最长公共子序列
给出两个字符串A B,求A与B的最长公共子序列字符串
思路:一开始直接字符串拼接做的,t了
String f[][];
String my_max(String a, String b) {
return (a.length()<b.length() ? b : a);
}
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++) {
if (s[i]==t[j]) f[i][j]=f[i-1][j-1]+s[i];
else f[i][j]=my_max(f[i-1][j], f[i][j-1]);
}
优化:我没有用好f[i][j]的意义,我只需要求出f[i][j]的最长长度,然后双指针判断就行了,逻辑见注释
import java.util.*;
import java.math.*;
import java.io.*;
class Solution {
int N=1005, n,m,f[][];
String get_lms(char[] s, char[] t) {
int i=n, j=m;
StringBuilder ans=new StringBuilder();
while (i>0 && j>0) {
if (s[i]==t[j]) {
ans.append(s[i]);
i--; j--;
} else { //(s的前i-1个字符和t的前j个的lms」比「s的前i个和t的前j-1个的lms)短,则证明我保留s的第i个字符更优
if (f[i-1][j]<f[i][j-1]) j--;
else i--;
}
}
return ans.reverse().toString();
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
String a=sc.next(), b=sc.next();
f=new int[N][N]; n=a.length(); m=b.length();
a=' '+a; b=' '+b;
char s[]=a.toCharArray(), t[]=b.toCharArray();
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++) {
if (s[i]==t[j]) f[i][j]=f[i-1][j-1]+s[i];
else f[i][j]=Math.max(f[i-1][j], f[i][j-1]);
}
System.out.println(get_lms(s,t));
}
}
public class Main{
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
最长公共子串
给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。
思路:记录最长长度与达到最长长度时的子串的结尾位置
const int N=5005;
class Solution {
public:
int f[N][N];
string LCS(string s, string t) {
int n=s.size(), m=t.size(), maxL=0, e=-1;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++) {
if (s[i-1]==t[j-1]) {
f[i][j]=f[i-1][j-1]+1;
} else {
f[i][j]=0;
}
if (f[i][j]>maxL)
maxL=f[i][j], e=i-1;
}
if (e==-1) return "-1";
return s.substr(e-maxL+1, maxL);
}
};