Algorithm 最长公共子串的DP记忆化方法
有人能提供两个字符串之间最长公共子字符串的记忆方法吗?我知道最底层的解决方案,但我不能自上而下地思考。Algorithm 最长公共子串的DP记忆化方法,algorithm,dynamic-programming,Algorithm,Dynamic Programming,有人能提供两个字符串之间最长公共子字符串的记忆方法吗?我知道最底层的解决方案,但我不能自上而下地思考。 预期时间复杂度-O(n^2)记忆是指缓存子问题的解决方案,以便以后使用。在最长公共子序列问题中,您尝试匹配两个子序列的子字符串,以查看它们是否匹配,并在内存中保留找到的最长子序列。以下是您正在寻找的Java解决方案(LCS的记忆版): 公共类最长公共子序列{ 私有静态HashMap缓存=新HashMap(); 私有静态整数计数=0,总计=0; 公用静态空干管(字符串SARG[]){ 扫描仪=新
预期时间复杂度-O(n^2)记忆是指缓存子问题的解决方案,以便以后使用。在最长公共子序列问题中,您尝试匹配两个子序列的子字符串,以查看它们是否匹配,并在内存中保留找到的最长子序列。以下是您正在寻找的Java解决方案(LCS的记忆版):
公共类最长公共子序列{
私有静态HashMap缓存=新HashMap();
私有静态整数计数=0,总计=0;
公用静态空干管(字符串SARG[]){
扫描仪=新的扫描仪(System.in);
字符串x=scanner.nextLine();
字符串y=scanner.nextLine();
int max=0;
字符串最长=”;
对于(int j=0;j而言,使用递归的记忆使用自顶向下的方法。
下面以使用科曼公司DP的LCS为例,是描述其工作原理的伪代码
MEMOIZED-LCS-LENGTH(X,Y)
m<-length[X]
n<-length[Y]
for(i<-1 to m)
do for(j<-1 to n)
c[i,j]<- -1
for(i<-1 to m)
c[i,0]<-0
for(j<-1 to n)
c[0,j]<-0
return RECURSIVE-LCS-LENGTH(X,Y,1,1)
RECURSIVE-LCS-LENGTH(X,Y,i,j)
if(c[i,j]!=-1)
return c[i,j]
//Above 2 line fetches the result if already present, instead of computing it again.
if(x[i]==y[j])
then c[i,j]<-RECURSIVE-LCS-LENGTH(X,Y,i+1,j+1)+1
else
c1<- RECURSIVE-LCS-LENGTH(X,Y,i+1,j)
c2<-RECURSIVE-LCS-LENGTH(X,Y,i,j+1)
if(c1<c2)
then c[i,j]<-c1
else c[i,j]<-c2
return c[i,j]
MEMOIZED-LCS-LENGTH(X,Y)
m自上而下的方法
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
string X, Y; //input strings
int ans, dp[105][105]; // ans : answer
int LCS(int n, int m) //our function return value of (n,m) state
{ // so that we can use the result in (n+1,m+1) state
if(n == 0 || m == 0) return 0; //in case of match in (n+1,m+1) state
if(dp[n][m] != -1) return dp[n][m];
LCS(n-1,m); //to visit all n*m states (try example: X:ASDF
LCS(n,m-1); // we call these states first Y:ASDFF)
if(X[n-1] == Y[m-1])
{
dp[n][m] = LCS(n-1,m-1) + 1;
ans = max(ans, dp[n][m]);
return dp[n][m];
}
return dp[n][m] = 0;
}
int main()
{
int t; cin>>t;
while(t--)
{
int n, m; cin>>n>>m; //length of strings
cin>>X>>Y;
memset(dp, -1, sizeof dp);
ans = 0;
LCS(n, m);
cout<<ans<<'\n';
}
return 0;
}
#包括
#包括
#包括
使用名称空间std;
字符串X,Y;//输入字符串
int ans,dp[105][105];//ans:回答
int LCS(int n,int m)//我们的函数返回(n,m)状态的值
{//这样我们就可以在(n+1,m+1)状态下使用结果
如果(n==0 | | m==0)在(n+1,m+1)状态下匹配,则返回0;//如果匹配
如果(dp[n][m]!=-1)返回dp[n][m];
LCS(n-1,m);//访问所有n*m个状态(尝试示例:X:ASDF
LCS(n,m-1);//我们首先称这些状态为Y:ASDFF)
如果(X[n-1]==Y[m-1])
{
dp[n][m]=LCS(n-1,m-1)+1;
ans=最大值(ans,dp[n][m]);
返回dp[n][m];
}
返回dp[n][m]=0;
}
int main()
{
int t;cin>>t;
而(t--)
{
int n,m;cin>>n>>m;//字符串的长度
cin>>X>>Y;
膜组(dp,-1,dp大小);
ans=0;
LCS(n,m);
cout下面描述了一个简单的解决方案。此处memo[n][m]
不存储
最大子字符串,但您可以将最大子字符串存储在pointer maxi中,如下所示:
#include<iostream>
#include<string>
using namespace std;
int lcs(string X,string Y,int n,int m,int *maxi,int memo[][8]) {
if(n==0||m==0) {
return 0;
}
int k=0;
int j=0;
if(memo[n-1][m-1]!=-1) {
return memo[n-1][m-1];
}
if(X[n-1]==Y[m-1]) {
memo[n-1][m-1] = 1+lcs(X,Y,n-1,m-1,maxi,memo);
if(*maxi<memo[n-1][m-1])
*maxi=memo[n-1][m-1];
}
else {
memo[n-1][m-1]=0;
}
int l = lcs(X,Y,n-1,m,maxi,memo);
int i = lcs(X,Y,n,m-1,maxi,memo);
return memo[n-1][m-1];
}
int main()
{
int n,m;
string X = "abcdxyze";
//string X = "abcd";
string Y = "xyzabcde";
n=X.length();
m=Y.length();
int memo[n][8];
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
memo[i][j]=-1;
}
}
int maxi=0;
int k = lcs(X,Y,n,m,&maxi,memo);
cout << maxi;
return 0;
}
#包括
#包括
使用名称空间std;
int lcs(字符串X、字符串Y、int n、int m、int*maxi、int memo[][8]){
如果(n==0 | | m==0){
返回0;
}
int k=0;
int j=0;
如果(备忘录[n-1][m-1]!=-1){
返回备忘录[n-1][m-1];
}
如果(X[n-1]==Y[m-1]){
备忘录[n-1][m-1]=1+lcs(X,Y,n-1,m-1,最大,备忘录);
if(*maxi递归加上python中的记忆。请注意,这段代码在Hackerearth和Geeksforgeks上部分被接受。对于更大的测试用例,它给出了MLE
import sys
sys.setrecursionlimit(1000000)
maxlen=0
t=None
def solve(s1, s2, n, m):
global maxlen, t
if n<=0 or m<=0:
return 0
if t[n][m]!=-1:
return t[n][m]
if s1[n-1]==s2[m-1]:
temp=1+solve(s1, s2, n-1, m-1)
maxlen=max(maxlen, temp)
t[n][m]=temp
return temp
t[n][m]=0
return 0
class Solution:
def longestCommonSubstr(self, S1, S2, n, m):
global maxlen, t
maxlen=0
t=[[-1]*(m+1) for i in range(n+1)]
for i in range(n+1):
for j in range(m+1):
solve(S1, S2, i, j)
return maxlen
if __name__=='__main__':
S1=input().strip()
S2=input().strip()
n=len(S1)
m=len(S2)
ob = Solution()
print(ob.longestCommonSubstr(S1, S2, n, m))
导入系统
系统设置递归限制(1000000)
maxlen=0
t=无
def解算(s1、s2、n、m):
全局maxlen,t
如果n这里是一个递归的自顶向下的方法:
public int lcsSubstr(char[] s1, char[] s2, int m, int n, int c) {
if (m == 0 || n == 0) {
return c;
}
if (s1[m-1] == s2[n-1]) {
c = lcsSubstr(s1, s2, m-1, n-1, c+1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m-1, n, 0));
}
return Math.max(c, c2);
}
public int lcsSubstrMemo(char[] s1, char[] s2, int m, int n, int c, int[][] t) {
if(m == 0 || n == 0) {
return c;
}
if (t[m-1][n-1] != -1) return t[m-1][n-1];
if(s1[m - 1] == s2[n - 1]) {
c = lcsSubstr(s1, s2, m - 1, n - 1, c + 1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m - 1, n, 0));
}
t[m - 1][n - 1] = Math.max(c, c2);
return t[m-1][n-1];
}
伪代码中有一个bug,它应该是if(c1>c2)
而不是if(c1
import sys
sys.setrecursionlimit(1000000)
maxlen=0
t=None
def solve(s1, s2, n, m):
global maxlen, t
if n<=0 or m<=0:
return 0
if t[n][m]!=-1:
return t[n][m]
if s1[n-1]==s2[m-1]:
temp=1+solve(s1, s2, n-1, m-1)
maxlen=max(maxlen, temp)
t[n][m]=temp
return temp
t[n][m]=0
return 0
class Solution:
def longestCommonSubstr(self, S1, S2, n, m):
global maxlen, t
maxlen=0
t=[[-1]*(m+1) for i in range(n+1)]
for i in range(n+1):
for j in range(m+1):
solve(S1, S2, i, j)
return maxlen
if __name__=='__main__':
S1=input().strip()
S2=input().strip()
n=len(S1)
m=len(S2)
ob = Solution()
print(ob.longestCommonSubstr(S1, S2, n, m))
public int lcsSubstr(char[] s1, char[] s2, int m, int n, int c) {
if (m == 0 || n == 0) {
return c;
}
if (s1[m-1] == s2[n-1]) {
c = lcsSubstr(s1, s2, m-1, n-1, c+1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m-1, n, 0));
}
return Math.max(c, c2);
}
public int lcsSubstrMemo(char[] s1, char[] s2, int m, int n, int c, int[][] t) {
if(m == 0 || n == 0) {
return c;
}
if (t[m-1][n-1] != -1) return t[m-1][n-1];
if(s1[m - 1] == s2[n - 1]) {
c = lcsSubstr(s1, s2, m - 1, n - 1, c + 1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m - 1, n, 0));
}
t[m - 1][n - 1] = Math.max(c, c2);
return t[m-1][n-1];
}