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 }