最大公共子串c语言,最长公共子串(动态规划)

来源:https://www.cnblogs.com/fanguangdexiaoyuer/p/11281179.html

1 描述

有两个字符串(可能包含空格),请找出其中最长的公共连续子串,输出其长度。(长度在1000以内)

例如:

输入:abcde bcd

输出:3

2 解析

1、把两个字符串分别以行和列组成一个二维矩阵。

2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。

3、通过查找出值为1的最长对角线就能找到最长公共子串。

比如:str=acbcbcef,str2=abcbced,则str和str2的最长公共子串为bcbce,最长公共子串长度为5。

针对于上面的两个字符串我们可以得到的二维矩阵如下:

268ee8601ec4cb9d59095fe51f8a6193.png

从上图可以看到,str1和str2共有5个公共子串,但最长的公共子串长度为5。

为了进一步优化算法的效率,我们可以再计算某个二维矩阵的值的时候顺便计算出来当前最长的公共子串的长度,即某个二维矩阵元素的值由record[i][j]=1演变为record[i][j]=1 +record[i-1][j-1],这样就避免了后续查找对角线长度的操作了。修改后的二维矩阵如下:

4009544e6332e8d3cf2fb6cf416374e5.png

递推公式为:

当A[i] != B[j],dp[i][j] = 0

当A[i] == B[j],

若i = 0 || j == 0,dp[i][j] = 1

否则 dp[i][j] = dp[i - 1][j - 1] + 1

3 代码

暴力法

public int getLCS(String s, String s2)

{

if (s == null || t == null)

{

return 0;

}

int l1 = s.length();

int l2 = t.length();

int res = 0;

for (int i = 0; i 

{

for (int j = 0; j 

{

int m = i;

int k = j;

int len = 0;

while (m 

len++;

m++;

k++;

}

res = Math.max(res, len);

}

}

return res;

}

动态规划

public int getLCS(String s, String t)

{

if (s == null || t == null)

{

return 0;

}

int result = 0;

int sLength = s.length();

int tLength = t.length();

int[][] dp = new int[sLength][tLength];

for (int i = 0; i 

for (int k = 0; k 

if (s.charAt(i) == t.charAt(k)) {

if (i == 0 || k == 0) {

dp[i][k] = 1;

} else {

dp[i][k] = dp[i - 1][k - 1] + 1;

}

result = Math.max(dp[i][k], result);

} else {

dp[i][k] = 0;

}

}

}

return result;

}

简化一下递推公式:

当A[i] != B[j],dp[i][j] = 0

否则 dp[i][j] = dp[i - 1][j - 1] + 1

全部都归结为一个公式即可,二维数组默认值为0

public int getLCS(String s, String t)

{

if (s == null || t == null)

{

return 0;

}

int result = 0;

int sLength = s.length();

int tLength = t.length();

int[][] dp = new int[sLength + 1][tLength + 1];

for (int i = 1; i <= sLength; i++) {

for (int k = 1; k <= tLength; k++) {

if (s.charAt(i - 1) == t.charAt(k - 1)) {

dp[i][k] = dp[i - 1][k - 1] + 1;

result = Math.max(dp[i][k], result);

}

}

}

return result;

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中实现动态规划最长公共子串算法可以通过以下步骤来实现: 1. 定义一个二维数组dp[m+1][n+1],其中m和n分别为两个字符串长度。 2. 初始化数组dp的第一行和第一列为0,即dp[i] = dp[j] = 0。 3. 使用两个循环遍历字符串的每个字符,i从1到m,j从1到n。 4. 如果两个字符相等,即str1[i-1] == str2[j-1],则dp[i][j] = dp[i-1][j-1] + 1。 5. 如果两个字符不相等,即str1[i-1] != str2[j-1],则dp[i][j] = 0。 6. 在循环过程中,记录最大的dp[i][j]值,以及对应的i和j的位置。 7. 循环结束后,最大的dp[i][j]就是最长公共子串长度。 8. 可以根据最长公共子串长度和i、j的位置,来获取最长公共子串的具体内容。 以下是一个示例代码: ```c #include <stdio.h> #include <string.h> void longestCommonSubstring(char* str1, char* str2) { int m = strlen(str1); int n = strlen(str2); int dp[m+1][n+1]; int maxLen = 0; int maxEndIndex = 0; // 初始化dp数组 for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { dp[i][j] = 0; } } // 计算dp数组 for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (str1[i-1] == str2[j-1]) { dp[i][j] = dp[i-1][j-1] + 1; if (dp[i][j] > maxLen) { maxLen = dp[i][j]; maxEndIndex = i - 1; } } else { dp[i][j] = 0; } } } // 获取最长公共子串 char longestSubstring[maxLen + 1]; strncpy(longestSubstring, &str1[maxEndIndex - maxLen + 1], maxLen); longestSubstring[maxLen] = '\0'; printf("最长公共子串: %s\n", longestSubstring); } int main() { char str1[] = "abcdefg"; char str2[] = "cdefgh"; longestCommonSubstring(str1, str2); return 0; } ``` 这段代码会输出最长公共子串:"cdef"。你可以根据需要修改字符串的内容进行测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值