<空间优化>

求两个字符串的最长公共子序列的长度。

输入:

第一行字符串 S1 
第二行字符串 S2 
(注:字符为英文字母,大小写均可。字符串长度大于等于1 ,各不大于10000)

输出:
数字 M ,为最长公共子序列长度。

例如:

输入:

BDCABA
ABCBDAB
输出:

4

 

  测试输入最长公共子序列-空间优化-BITOJ 期待的输出最长公共子序列-空间优化-BITOJ 时间限制最长公共子序列-空间优化-BITOJ 内存限制最长公共子序列-空间优化-BITOJ 额外进程最长公共子序列-空间优化-BITOJ
测试用例 1 以文本方式显示
  1. ABKLMNABCDI↵
  2. ABCDEFGHIJKLMNOPQRSTUVWXYZ↵
以文本方式显示
  1. 6↵
1秒 256KB 0

思路:典型的动态规划问题

dp[i][j]:表示a串前i个字符与b串前j个字符的最长公共字符的个数,dp[n][m]即为最后的结果。

显然:

dp[i][j]=dp[i-1][j-1]+1; if(a[i]==b[j])
dp[i][j]=max(dp[i-1][j],dp[i][j-1]); if(a[i]!=b[j])

于是可以递推下去,求解dp[n][m]。

这里提出一点小小的空间优化:

递推的时候,我们需要求解dp[i][j],因此需要用到dp[i-1][j-1],dp[i-1][j],dp[i][j-1];这三个状态。

可以看出不需要dp[i-2],dp[i-3]...等状态,于是这里可以有空间优化。

最典型的奇偶优化,因为只需要存储dp[i],dp[i-1]这两个相邻的状态,i,i-1,二者必须是一个奇数一个偶数,所以奇偶优化就显得很方便。

奇偶递推式:

dp[i&1][j]=dp[(i-1)&1][j-1]+1;if(a[i]==b[j])
dp[i&1][j]=max2(dp[(i-1)&1][j],dp[i&1][j-1]);if(a[i]!=b[j])

这样dp数组可以优化到:2*m,m为字符串中长度最短的那个。

View Code
 1 #include<stdlib.h>
2 #include<string.h>
3 #include<stdio.h>
4 #define max2(a,b) (a>b)?a:b
5 #define N 10001
6
7 char str[2][N];
8 int dp[2][N];
9 int main()
10 {
11 int i,j,k,n,m;
12 while(~scanf("%s%s",str[0],str[1]))
13 {
14 n=strlen(str[0]);
15 m=strlen(str[1]);
16 memset(dp,0,sizeof(dp));
17 for(i=1;i<=n;i++)
18 for(j=1;j<=m;j++)
19 if(str[0][i-1] == str[1][j-1])
20 dp[i&1][j]=dp[(i-1)&1][j-1]+1;
21 else
22 dp[i&1][j]=max2(dp[(i-1)&1][j],dp[i&1][j-1]);
23 printf("%d\n",dp[n&1][m]);
24 }
25 return 0;
26 }



相关文章:

  • 2022-12-23
  • 2022-01-19
  • 2021-04-14
猜你喜欢
  • 2021-08-06
  • 2021-04-20
  • 2021-11-15
  • 2021-07-29
  • 2021-11-20
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案