C语言算法-解答不同的子序列算法问题的C语言实现
题目描述
给定一个字符串 s 和一个字符串 t,计算在 s 的子序列中 t 出现的个数。
字符串的一个子序列是指,通过删除一些字符(或不删除)且不干扰剩余字符相对位置所形成的新字符串。例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是。
题目保证答案符合 32 位带符号整数范围。
算法思路
动态规划是解决此类问题的常用方法。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示字符串 s
的前 i
个字符中包含字符串 t
的前j
个字符的子序列个数。
状态转移方程为:
- 如果
s[i-1]
==t[j-1]
,则dp[i][j]
=dp[i-1][j-1]
+dp[i-1][j]
; - 否则,
dp[i][j]
=dp[i-1][j]
。
代码实现
int numDistinct(char *s, char *t) {
int sLen = strlen(s);
int tLen = strlen(t);
int dp[sLen + 1][tLen + 1];
memset(dp, 0, sizeof(dp));
for (int i = 0; i <= sLen; ++i) {
dp[i][0] = 1;
}
for (int i = 1; i <= sLen; ++i) {
for (int j = 1; j <= tLen; ++j) {
if (s[i - 1] == t[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[sLen][tLen];
}
算法分析
- 时间复杂度:O(m * n),其中 m 和 n 分别为字符串 s 和 t 的长度。
- 空间复杂度:O(m * n),使用了二维数组 dp。
示例和测试
#include <stdio.h>
int main() {
char s[] = "rabbbit";
char t[] = "rabbit";
int result = numDistinct(s, t);
printf("The number of distinct subsequences is: %d\n", result);
return 0;
}
输出结果:
The number of distinct subsequences is: 3
总结
本文介绍了使用动态规划算法解决字符串中不同子序列问题。动态规划的核心思想是利用已经计算好的状态来推导新的状态,从而降低问题的复杂度。这种方法在处理字符串问题中非常有效。