H - Common Subsequence题解(求两个字符串的最长公共子序列)
[题目传送门](Problem - 1159 (hdu.edu.cn))
题目大意:给两个字符串,求相同子序列的最大长度。
子序列:一个串的子串是指该串的一个连续的局部。如果不要求连续,则可称为它的子序列。
s1, s2,设n为s1的长度,m为s2的长度
这个题没有说明字符串的长度,交题测试后发现长度小于1000;此时数据并不大,可以开一个二维数组跑动态规划
可以想象成两个字符串分别由两个指针从前往后跑;
i 和 j 分别表示 s1[1~i] , s2[1~j] 字符串下标从1开始
所以 f ( i, j ) 表示 s1 和 s2 两种状态下相同子序列的最大长度
**然后注意初始化,此时 f [ i ][ 0 ] 和 f [ 0 ][ j ] 应该都为 0, 因为字符串和 “空” 的子序列长度为 0。
1 for (int i = 1; i <= n; i++)//核心代码 2 { 3 for (int j = 1; j <= m; j++) 4 { 5 if (s1[i] == s2[j]) 6 f[i][j] = f[i - 1][j - 1] + 1; 7 else 8 f[i][j] = max(f[i][j - 1], f[i - 1][j]); 9 } 10 }
这里有两种情况,如果 s1[ i ] == s2[ j ] 此时可以确定 s1, s2 有一个单位长度的相同子序列,所以
此时状态为之前的状态加1即:
f [ i ][ j ] = f [ i - 1 ][ j - 1 ] + 1;
第二种情况就是s1[ i ] != s2[ j ], 此时也有不同的情况,因为我们并不知道 s1[ i ] 和 s2[ j ] 那个一个字符不
包含在最长公共序列里面,所以:
f[ i ][ j ] = max(f[ i ][ j - 1 ], f [ i - 1 ][ j ]);
下面是完整代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <vector> 5 #include <cmath> 6 #include <cstring> 7 #define ll long long 8 #define ull unsigned long long 9 #define ci const int 10 using namespace std; 11 ci N = 1e3 + 7; 12 char s1[N], s2[N]; 13 int f[N][N]; 14 int main() 15 { 16 while (scanf("%s%s", s1 + 1, s2 + 1) !=EOF)//这里输入的 s1 和 s2 都是从下标 1 开始存的 17 { 18 memset(f, 0, sizeof f);//动规数组初始化 19 int n = strlen(s1 + 1), m = strlen(s2 + 1); 20 for(int i = 1; i <= n; i++) 21 f[i][0] = 0; 22 for(int i = 1; i <= m; i++) 23 f[0][i] = 0; 24 //vector<vector<int>> f(n, vector<int>(m)); 25 for (int i = 1; i <= n; i++) 26 { 27 for (int j = 1; j <= m; j++) 28 { 29 if (s1[i] == s2[j]) 30 f[i][j] = f[i - 1][j - 1] + 1; 31 else 32 f[i][j] = max(f[i][j - 1], f[i - 1][j]); 33 } 34 } 35 cout << f[n][m] << "\n"; 36 } 37 return 0; 38 }

浙公网安备 33010602011771号