NYOJ-36 最长公共子序列 动态规划

最长公共子序列

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 3
描述
咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。
tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
输入
第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.
输出
每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。
样例输入
2
asdf
adfsd
123abc
abc123abc
样例输出
3
6

动态规则经典题,详细讲解参考算法 导论P208。


01. #include <iostream>
02. #include <string>
03. using namespace std;
04.  
05. int c[1002][1002];
06.  
07. void lcs(string &a,string &b,int n,int m)
08. {
09. for(int i=0;i<=m;i++)
10. c[0][i]=0;
11. for(int i=0;i<=n;i++)
12. c[i][0]=0;
13. for(int i=1;i<=n;i++)
14. {
15. for(int j=1;j<=m;j++)
16. {
17. if(a[i-1]==b[j-1])
18. c[i][j]=c[i-1][j-1]+1;
19. else if(c[i][j-1]>c[i-1][j])
20. c[i][j]=c[i][j-1];
21. else
22. c[i][j]=c[i-1][j];
23. }
24. }
25.  
26. }
27.  
28. int main()
29. {
30. string a,b;
31. int t;
32. cin>>t;
33. while(t--)
34. {
35. cin>>a>>b;
36. lcs(a,b,a.size(),b.size());
37. cout<<c[a.size()][b.size()]<<endl;
38. }
39. return 0;
40. }

然而上面的算法空间复杂度还是挺大的,算法导论书中习题要求只用min(m,n)+O(1)的空间完成。于是就有了如下的算法:

只用一维数组dp[N]。

old 变量是用来表示dp[i-1][j-1],dp[j-1]表示dp[i][j-1],dp[j]表示dp[i-1][j]。

比如,当我们开始处理i=4的时候,从j=1开始,一开始old表示dp[3][0],肯定为0。然后用临时变量tmp记下这时的dp[j]这时的dp[j]还没有被改变,也就是说,这里的dp[j]还是i=3的时候求得的dp[j],而其对于j+1来说就是dp[i-1][j-1]。此时的dp[j]对当前的j来说,就是dp[i-1][j],而dp[j-1]已经在 j的前一刻被处理过了,也就等阶于dp[i][j-1]。OVER。

#include <iostream>
02. #include <string>
03. #include <string.h>
04. using namespace std;
05.  
06. int dp[1001];
07.  
08. int main()
09. {
10. int t;
11. cin>>t;
12. while(t--)
13. {
14. string a,b;
15. cin>>a>>b;
16. memset(dp,0,sizeof(dp));
17. int al=a.size(),bl=b.size();
18. int old,tmp;
19. for(int i=1;i<=al;i++)
20. {
21. old=0;
22. for(int j=1;j<=bl;j++)
23. {
24. tmp=dp[j];
25. if(a[i-1]==b[j-1])
26. dp[j]=old+1;
27. else if(dp[j-1]>dp[j])
28. dp[j]=dp[j-1];
29. old=tmp;
30. }
31. }
32. cout<<dp[bl]<<endl;
33. }
34. return 0;
35. }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
孪生素数是指两个素数之间的差值为2的素数对。通过筛选法可以找出给定素数范围内的所有孪生素数的组数。 在引用的代码中,使用了递归筛选法来解决孪生素数问题。该程序首先使用循环将素数的倍数标记为非素数,然后再遍历素数数组,找出相邻素数之间差值为2的素数对,并统计总数。 具体实现过程如下: 1. 定义一个数组a[N,用来标记数字是否为素数,其中N为素数范围的上限。 2. 初始化数组a,将0和1标记为非素数。 3. 输入要查询的孪生素数的个数n。 4. 循环n次,每次读入一个要查询的素数范围num。 5. 使用两层循环,外层循环从2遍历到num/2,内层循环从i的平方开始,将素数的倍数标记为非素数。 6. 再次循环遍历素数数组,找出相邻素数之间差值为2的素数对,并统计总数。 7. 输出总数。 至此,我们可以使用这个筛选法的程序来解决孪生素数问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python用递归筛选法求N以内的孪生质数(孪生素数)](https://blog.csdn.net/weixin_39734646/article/details/110990629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [NYOJ-26 孪生素数问题](https://blog.csdn.net/memoryofyck/article/details/52059096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值