(DP)51NOD 1006 最长公共子序列&1092 回文字符串

1006
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
比如两个串为:
 
abcicba
abdkscab
 
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
 

输入

第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)

输出

输出最长的子序列,如果有多个,随意输出1个。

输入样例

abcicba
abdkscab

输出样例

abca

解:dp题,画一画表格可以帮助理解。
 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 #define CLR(x) memset(x, 0, sizeof x)
 5 #define MAX(a,b) (a > b ? a : b)
 6 
 7 char a[1005], b[1005],c[1005];
 8 int dp[1005][1005];
 9 
10 int main()
11 {
12     while (scanf_s("%s%s", a,1005, b,1005) != EOF)
13     {
14         int lena = strlen(a),lenb=strlen(b);
15         for (int i = 1; i <= lena; i++)
16         {
17             for (int j = 1; j <= lenb; j++)
18             {
19                 if (a[i - 1] == b[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
20                 else dp[i][j] = MAX(dp[i - 1][j], dp[i][j - 1]);
21             }
22         }
23         for (int i = dp[lena][lenb],j = 0; i > 0;)
24         {
25             if (dp[lena][lenb] > dp[lena - 1][lenb]&& dp[lena][lenb] > dp[lena][lenb - 1])
26             {
27                 c[i-1]=a[lena - 1];
28                 lena--; lenb--;
29                 i--;
30             }
31             else
32             {
33                  int mode = dp[lena - 1][lenb]>dp[lena][lenb - 1] ? 1:0;
34                  if (mode) lena--;
35                  else lenb--;
36             }
37         }
38         printf("%s\n",c);
39     }
40 }

 

1092

回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。每个字符串都可以通过向中间添加一些字符,使之变为回文字符串。
例如:abbc 添加2个字符可以变为 acbbca,也可以添加3个变为 abbcbba。方案1只需要添加2个字符,是所有方案中添加字符数量最少的。
 

输入

输入一个字符串Str,Str的长度 <= 1000。

输出

输出最少添加多少个字符可以使之变为回文字串。

输入样例

abbc

输出样例

2

解:求最长字符串的变形。针对上一题的做法优化了一下空间复杂度。
 1 #include<stdio.h>
 2 #include<string.h>
 3 #define Max(a,b) ((a)>(b)?(a):(b))
 4 char a[1001];
 5 int dp[2][1001];
 6 int main()
 7 {
 8     while (scanf_s("%s", a, 1001) != EOF)
 9     {
10         int len = strlen(a), ans, tmp = 0;
11         memset(dp, 0, sizeof dp);
12         for (int i = 0; i < len; ++i)
13         {
14             for (int j = len - 1; j >= 0; --j)
15             {
16                 if (a[i] == a[j]) dp[tmp][j] = dp[tmp ^ 1][j + 1] + 1;
17                 else dp[tmp][j] = Max(dp[tmp ^ 1][j], dp[tmp][j + 1]);
18             }
19             tmp ^= 1;
20         }
21         ans = len - dp[tmp ^ 1][0];
22         printf("%d\n", ans);
23     }
24     return 0;
25 }

 

 

转载于:https://www.cnblogs.com/Ekalos-blog/p/11020146.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值