我们有两个字符串m和n,如果它们的子串a和b内容相同,则称a和b是m和n的公共子序列。子串中的字符不一定在原字符串中连续。
例如字符串“abcfbc”和“abfcab”,其中“abc”同时出现在两个字符串中,因此“abc”是它们的公共子序列。此外,“ab”、“af”等都是它们的字串。
现在给你两个任意字符串(不包含空格),请帮忙计算它们的最长公共子序列的长度。
输入包含多组数据。
每组数据包含两个字符串m和n,它们仅包含字母,并且长度不超过1024。
对应每组输入,输出最长公共子序列的长度。
abcfbc abfcab programming contest abcd mnp
4 2 0
// 参考自id:没有头的小蘑菇
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main()
{
string s1, s2;
while(cin>>s1>>s2)
{
vector<vector<int>> dp(s1.size()+1,vector<int>(s2.size()+1, 0));
for(int i = 1; i <= s1.size(); i++)
for(int j = 1; j<= s2.size(); j++)
{
if(s1[i-1] == s2[j-1])
dp[i][j] = dp[i-1][j-1]+1;
else
dp[i][j] = dp[i-1][j] > dp[i][j-1] ? dp[i-1][j] : dp[i][j-1];
}
cout<<dp[s1.size()][s2.size()]<<endl;
}
return 0;
}
ef findAllIndexs(string1, s): """ string1: 带查找的字符串 s: 带查找的字符 查找当前字符在string1中的所有下标 """ indexlist = [] flag = len(string1) while flag != -1 : flag = string1.rfind(s,0,flag) if flag > -1: indexlist.append(flag) return (s,indexlist) def LCS_2(string1, string2): """ string1: 第一个字符串 string2: 第二个字符串 思路:把lcs问题转化为lis问题 """ def conver_lis(string1,string2): """ string1: 第一个字符串 string2: 第二个字符串 思路:求出string1 中每个字符在string2中的下标,下标从大到小排列 其时间复杂度为O(nlogn) """ lis = [] k = set() for s in string1: if s not in k: ch,ind = findAllIndexs(string2, s) if len(ind) != 0: lis.extend(ind) return lis lis = conver_lis(string1, string2) if len(lis) == 0: return 0 q = [] for i in lis: pos = bisect.bisect_left(q,i) if len(q) == pos: q.append(i) else: q[pos] = i return len(q) while True: try: string1,string2 = input().split() res = LCS_2(string1, string2) print(res) except: break..........时间复杂度为nlogn才能给过,c++只要n^2 就给过,欺负语言嘛
try:
while True:
string1,string2 = input().split()
result = [[0 for i in range(len(string2)+1)] for j in range(len(string1)+1)]
#result[i][j]保存string1前i个子串和string2前j个子串的公共子序列
for i in range(1,len(string1)+1):
for j in range(1,len(string2)+1):
result[i][j] = max(result[i-1][j],result[i][j-1])
if string1[i-1]==string2[j-1]:
result[i][j] = result[i-1][j-1]+1 #等于子串都减一的公共子序列长度加一
print(result[-1][-1])
except Exception:
pass
//和前面问题的大佬学到的,可以试着优化一下空间效率,只保存一行,每次保存需要的值更新下一行即可
// write your code here
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
String s1=in.next();
String s2=in.next();
int[] dp=new int[s2.length()+1];
for(int i=0;i<s1.length();i++){
int pre=dp[0];
for(int j=1;j<=s2.length();j++){
int temp=dp[j];
if(s1.charAt(i)==s2.charAt(j-1))
dp[j]=Math.max(dp[j],Math.max(dp[j-1],pre+1));
else
dp[j]=Math.max(dp[j],Math.max(dp[j-1],pre));
pre=temp;
}
}
System.out.println(dp[s2.length()]);
}
in.close();
}
}
//注意类名必须是Main,才能进行调试
//使用res矩阵,存储子问题的结果。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String[] str = in.nextLine().split(" ");
int resLen = longestCommonSubsequence1(str[0], str[1]);
System.out.println( resLen );
}
}
private static int longestCommonSubsequence1(String s1, String s2) {
int m = s1.length();
int n = s2.length();
if(m==0||n==0) return 0;
//存储子问题的结果。
//行和列的索引表示:取字符串从左到中间的子串的长度
//索引范围:[0-m]和[0-n]
int[][] res = new int[m+1][n+1];
//逐行添加子问题的结果。 第一行和第一列值未初始化值,系统默认为0
//i或j表示取字符串从左到中间的子串的长度
for(int i=0; i<=m; i++){
for(int j=0; j<=n; j++){
if(i==0||j==0)
res[i][j] = 0;
else if(s1.charAt(i-1)==s2.charAt(j-1)) //i而j表示的是子串长度,所以这里要减1
res[i][j] = res[i-1][j-1] + 1;
else{
res[i][j] = Math.max(res[i-1][j], res[i][j-1]);
}
}
}
return res[m][n];
}
}
#在编译器上可以成功运行,在牛客上总是提示运行超时,不知道怎么办了
while True:
try:
A, B = map(str, raw_input('').split())
n = len(A)
m = len(B)
matrix = [0] * m * n
for i in range(n):
if A[i] == B[0]:
for j in range(i, n):
matrix[j] = 1
for i in range(m):
if B[i] == A[0]:
for j in range(i, m):
matrix[j * n] = 1
for i in range(1, m):
for j in range(1, n):
if B[i] == A[j]:
matrix[i * n + j] = max(matrix[(i - 1) * n + j - 1] + 1, matrix[(i - 1) * n + j], matrix[i * n + j - 1])
else:
matrix[i * n + j] = max(matrix[(i - 1) * n + j], matrix[i * n + j - 1])
print matrix[m * n - 1]
except:
break
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while (cin.hasNext()) {
String str1 = cin.next();
String str2 = cin.next();
lcs(str1, str2);
}
}
public static void lcs(String str1, String str2) {
int r = str1.length();
int c = str2.length();
if (str1.equals(str2)) {
System.out.println(str1.length());
} else {
int[][] dp = new int[r][c];
int max = 0;
for (int i = 0; i < r; i++) {
if (str1.charAt(i) != str2.charAt(0))
dp[i][0] = 0;
else {
for (int j = i; j < r; j++)
dp[j][0] = 1;
break;
}
}
for (int i = 0; i < c; i++) {
if (str2.charAt(i) != str1.charAt(0))
dp[0][i] = 0;
else {
for (int j = i; j < c; j++)
dp[0][j] = 1;
break;
}
}
for (int i = 1; i < r; i++) {
for (int j = 1; j < c; j++) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
if (str1.charAt(i) == str2.charAt(j))
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1);
max = dp[i][j] > max ? dp[i][j] : max;
}
}
System.out.println(max);
}
}
}
import java.util.Scanner;
/**
* Created by Olive on 2017/8/6.
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String strm = in.next();
String strn = in.next();
int cnt = longestCSS(strm, strn);
System.out.println(cnt);
}
}
public static int longestCSS(String m, String n){
if(m == null || m.length() == 0 || n == null || n.length() == 0 )
return 0;
int r = m.length();
int c = n.length();
// dp[i][j]表示m的0~i与m的0~j子串的最长公共子串长度
int[][] dp = new int[r][c];
if(m.charAt(0) == n.charAt(0))
dp[0][0] = 1;
for(int i = 1; i < r; i++){
dp[i][0] = m.charAt(i) == n.charAt(0) ? 1 : 0;
dp[i][0] = Math.max(dp[i][0], dp[i - 1][0]);
}
for(int j = 1; j < c; j++){
dp[0][j] = m.charAt(0) == n.charAt(j) ? 1 : 0;
dp[0][j] = Math.max(dp[0][j], dp[0][j - 1]);
}
// dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
// 若m.charAt(i) == n.charAt(j):
// dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1] + 1);
for(int i = 1; i < r; i++){
for(int j = 1; j < c; j++){
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
if(m.charAt(i) == n.charAt(j))
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1);
}
}
return dp[r-1][c-1];
}
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int dp[1030][1030];
char a[1030];
char b[1030];
int main()
{
while(cin>>a>>b){
memset(dp,0,sizeof(dp));
int lena = strlen(a);
int lenb = strlen(b);
for(int i=1;i<=lena;i++){
for(int j=1;j<=lenb;j++){
if(a[i-1]==b[j-1])
dp[i][j] = dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
cout<<dp[lena][lenb]<<endl;
}
return 0;
}
dp[i][j]表示a[i]以及之前的元素和b[i]以及之前的元素最大公共序列长度。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string A, B;
while(cin >> A >> B) {
int aLength = A.length();
int bLength = B.length();
vector<vector<int> > dp(aLength, vector<int>(bLength, 0));
// 初始化边界
dp[0][0] = (A[0] == B[0])?1:0;
for(int i=1; i<aLength; i++) {
dp[i][0] = (A[i] == B[0]) ? 1 : 0;
dp[i][0] = max(dp[i-1][0], dp[i][0]);
}
for(int j=1; j<bLength; j++) {
dp[0][j] = (A[0] == B[j]) ? 1 : 0;
dp[0][j] = max(dp[0][j-1], dp[0][j]);
}
// 计算
for(int i=1; i<aLength; i++) {
for(int j=1; j<bLength; j++) {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
if(A[i] == B[j]) {
dp[i][j] = max(dp[i][j], dp[i-1][j-1]+1);
}
}
}
cout << dp[aLength-1][bLength-1] << endl;
}
return 0;
}
package go.jacob.day911;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str1 = sc.next();
String str2 = sc.next();
System.out.println(LCS(str1, str2));
}
sc.close();
}
private static int LCS(String str1, String str2) {
int len1 = str1.length(), len2 = str2.length();
int[][] res = new int[len1 + 1][len2 + 1];
for (int i = 0; i < len1; i++) {
for (int j = 0; j < len2; j++) {
int cur = 0;
if (str1.charAt(i) == str2.charAt(j))
cur++;
res[i + 1][j + 1] = maxNum(res[i][j] + cur, res[i][j + 1], res[i + 1][j]);
}
}
return res[len1][len2];
}
/*
* 返回三者最大值
*/
private static int maxNum(int i, int j, int k) {
int max = i;
max = j > max ? j : max;
max = k > max ? k : max;
return max;
}
}
import java.util.*;
public class Main {
//最长公共子序列 动态规划
//问题:字符串s1长度为m,字符串s2长度为n,求其最长公共子序列
//状态:f(i,j)字符串s1中以i结尾的字符串和s2中以j结尾的字符串的最长公共子序列的长度
//状态转移:f(i,j)= s1[i]==s2[j] ? f(i-1,j-1)+1 : max(f(i-1,j),f(i,(j-1))
public static int common(String s1, String s2) {
int m = s1.length();
int n = s2.length();
//动态规划 二维数组初始化
int[][] dp = new int[m+1][n+1];
for (int i = 0; i < m + 1; i++) {
dp[i][0] = 0;
}
for (int i = 0; i < n + 1; i++) {
dp[0][i] = 0;
}
for (int i = 1; i < m+1; i++) {
for (int j = 1; j < n+1; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[m][n];
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String s1 = in.next();
String s2 = in.next();
System.out.println(common(s1, s2));
}
}
} import java.util.*;
public class Main{
public static int LCS(String m,String n){
int lenm = m.length();
int lenn = n.length();
int[][] dp = new int[lenm+1][lenn+1];
for(int i = 1;i <= lenm;i++){
for(int j = 1;j <= lenn;j++){
if(m.charAt(i - 1) == n.charAt(j - 1)){
dp[i][j] = dp[i - 1][j - 1] + 1;
}else{
dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - 1]);
}
}
}
return dp[lenm][lenn];
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String m = sc.next();
String n = sc.next();
int res = LCS(m,n);
System.out.println(res);
}
}
} #include<bits/stdc++.h>
#include<string>
using namespace std;
int LongestCommomSequence(string& str1,string& str2){
if(str1.size()==0||str2.size()==0){
return 0;
}
int m=str1.size();
int n=str2.size();
str1='0'+str1;
str2='0'+str2;
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(str1[i]==str2[j]){
dp[i][j]=1+dp[i-1][j-1];
}else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m][n];
}
int main(){
string s1,s2;
while(cin>>s1>>s2){
cout<<LongestCommomSequence(s1,s2)<<endl;
}
return 0;
} #include<iostream>
#include<string>
#include<vector>
using namespace std;
int main(){
string s1,s2;
while(cin>>s1>>s2){
vector<vector<int>> dp(s1.size()+1,vector<int>(s2.size()+1,0));//dp[i][j]表示s1[0..i]和s2[0..j]的最长公子序列长度
for(int i =1;i<=s1.size();i++){
for(int j=1;j<=s2.size();j++){
if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=dp[i-1][j]>dp[i][j-1]?dp[i-1][j]:dp[i][j-1];
}
}
cout<<dp[s1.size()][s2.size()]<<endl;
}
return 0;
} #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int lcs(string str1, string str2) { int len1 = str1.length(); int len2 = str2.length(); vector<vector<int>> c(len1+1, vector<int>(len2+1)); for (uint16_t i = 0; i < len1; i++) { for (uint16_t j = 0; j < len2; j++) { if (str1[i] == str2[j]) { c[i+1][j+1] = c[i][j] + 1; } else { c[i+1][j+1] = max(c[i+1][j], c[i][j + 1]); } } } return c[len1][len2];
}
int main()
{ int r; string a, b; while (cin >> a >> b) { if (a.empty() || b.empty()) { break; } r = lcs(a, b); cout << r << endl; }
}
#include<iostream>
#include<string>
using namespace std;
int main(void){ string A,B; int res; while(getline(cin,A,' ')&&getline(cin,B,'\n')){ int lenA = A.size()+1; int lenB = B.size()+1; int C[lenB][lenA]; for(int i = 0;i<lenA;i++){ C[0][i] = 0; } for(int i = 1;i<lenB;i++){ C[i][0] = 0; } for(int i = 1;i<lenB;i++){ for(int j = 1;j<lenA;j++){ if(B[i-1]==A[j-1]) { C[i][j] = C[i-1][j-1]+1; } else C[i][j] = max(C[i-1][j],C[i][j-1]); } } res = C[lenB-1][lenA-1]; cout<<res<<endl; } return 0;
}