最长公共子序列-空间优化-BITOJ
<空间优化>
求两个字符串的最长公共子序列的长度。
输入:
第一行字符串 S1
第二行字符串 S2
(注:字符为英文字母,大小写均可。字符串长度大于等于1 ,各不大于10000)
输出:
数字 M ,为最长公共子序列长度。
例如:
输入:
BDCABA
ABCBDAB
输出:
4
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
|
以文本方式显示
|
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为字符串中长度最短的那个。
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 }
posted on 2012-03-16 13:23 kevinkitty 阅读(1958) 评论(5) 编辑 收藏 举报