给定两个只包含小写字母的字符串,计算两个字符串的最大公共子串的长度。
注:子串的定义指一个字符串删掉其部分前缀和后缀(也可以不删)后形成的字符串。 数据范围:字符串长度:
进阶:时间复杂度:,空间复杂度:
#include <stdio.h> #include <string.h> int longest_substring(char *str1, char *str2) { int m = strlen(str1); int n = strlen(str2); // 创建二维数组dp int dp[m+1][n+1]; // 初始化最大长度为0 int max_len = 0; // 遍历两个字符串的每一个字母 for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { // 初始化边界条件 if (i == 0 || j == 0) { dp[i][j] = 0; } // 当两个字母相等时,更新dp[i][j]为前一个对角线上的数字加1 else if (str1[i-1] == str2[j-1]) { dp[i][j] = dp[i-1][j-1] + 1;//表示子串相等的长度 // 更新最大长度 if (dp[i][j] > max_len) { max_len = dp[i][j]; } } else { dp[i][j] = 0; } } } return max_len; } int main() { //输入 char str1[151] = {0}; char str2[151] = {0}; scanf("%s",str1); scanf("%s",str2); //查找 int len = longest_substring(str1, str2); //输出 printf("%d\n", len); return 0; }
#include <stdio.h> #include <string.h> /* 思路: 使用 较短子串作为公共子串假设去长子串里使用strstr进行判断。 对于短子串,使用两个循环,一是子串长度,二是该长度在短子串里的取值。 题目要求最大公共子串,那子串长度就从最大开始减减 */ int ss(int len_short, char *src, char *parent) { int i,res; int tmp_len = len_short; char tmp[len_short+ 1]; memset(tmp, 0, len_short+ 1); while(tmp_len) { for(i = 0; i <= (len_short - tmp_len); i++){ strncpy(tmp, &src[i], tmp_len); if(strstr(parent, tmp)) { return tmp_len; } memset(tmp, 0, len_short+ 1); } tmp_len--; memset(tmp, 0, len_short+ 1); } return tmp_len; } int main() { int len_a, len_b,len_short, i, ret; char a[151] = {0}; char b[151] = {0}; gets(a); gets(b); len_a = strlen(a); len_b = strlen(b); if(len_a < len_b) { len_short = len_a; ret = ss(len_short, a, b); } else { len_short = len_b; ret = ss(len_short, b, a); } printf("%d\n", ret); return 0; }
#include <stdio.h> #include <string.h> int main() { char str1[150]={0}, str2[150]={0}; int i, j, m, n, count; int max=0; scanf("%s %s", &str1, &str2); for(i=0;i<strlen(str1);i++) { for(j=0;j<strlen(str2);j++) { count=0; m=i; n=j; while(str1[m]==str2[n] && str1[m]!='\0') { count++; m++; n++; } max=count>max ? count : max; } } printf("%d",max); return 0; }
#include <stdio.h> #include <string.h> //dp[i][j]表示以字符串str1中第i个字符和str2中第j个字符为最后一个元素所构成的最长公共子串 int main() { char str1[150] = {}; char str2[150] = {}; int dp[151][151] = {0}; scanf("%s\n%s", str1,str2); int len1 = strlen(str1); int len2 = strlen(str2); int max_len = 0; for(int i=1; i<=len1; i++) { for(int j=1; j<=len2; j++) { if(str1[i-1] == str2[j-1]) { dp[i][j] = dp[i-1][j-1] + 1; if(max_len < dp[i][j]) max_len = dp[i][j]; } else { dp[i][j] = 0; } } } printf("%d",max_len); return 0; }
C动态规划 #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char str1[155], str2[155]; scanf("%s%s", str1, str2); int len1 = strlen(str1), len2 = strlen(str2), i, j, dp[len1][len2], commonlen = 0; memset(dp, 0, sizeof(int) * len1 * len2); for(i = 0; i < len1; i++){ if(str1[i] == str2[0]){ dp[i][0] = 1; commonlen = 1; } } for(i = 0; i < len2; i++){ if(str2[i] == str1[0]){ dp[0][i] = 1; commonlen = 1; } } for(i = 1; i < len1; i++){ for(j = 1; j < len2; j++){ if(str1[i] == str2[j]){ dp[i][j] = dp[i-1][j-1] + 1; commonlen = commonlen > dp[i][j] ? commonlen : dp[i][j]; } } } printf("%d\n", commonlen); return 0; }
#include <stdio.h> #include <string.h> #define STR_LEN 151 int GetCommonLen(char *min, char *max) { int len = 0; for (int i = 0; i < strlen(min); i++) { if (min[i] == max[i]) { len++; } else { break; } } return len; } int main(void) { char s1[STR_LEN]; char s2[STR_LEN]; while (gets(s1) && gets(s2)) { int len1 = strlen(s1); int len2 = strlen(s2); int min; int max; char *mins; char *maxs; if (len1 > len2) { min = len2; max = len1; mins = s2; maxs = s1; } else { min = len1; mins = s1; max = len2; maxs = s2; } int len = 0; for (int i = 0; i < min; i++) { for (int j = 0; j < max; j++) { // 从相同的地方向后寻找 if (mins[i] == maxs[j]) { int tmp = GetCommonLen(mins + i, maxs + j); len = len > tmp ? len : tmp; } } } printf("%d\n", len); } }
#include <stdio.h> int main() { int len1 = 0, len2 = 0; int line = 0; char array1[1024], array2[1024]; char buff; while(scanf("%c",&buff) != EOF) { if(buff == '\n') line++; else { if(0 == line) { array1[len1++] = buff; } else if(1 == line) { array2[len2++] = buff; } } if(2 == line) { int maxlen = 0; int map[len1][len2]; for(int i = 0; i < len1; i++) { for(int j = 0; j < len2; j++) { if(array1[i] == array2[j]) { if(i==0 || j==0) map[i][j] = 1; else map[i][j] = map[i-1][j-1]+1; maxlen = maxlen < map[i][j] ? map[i][j]:maxlen; } else map[i][j] = 0; } } printf("%d\n",maxlen); line = 0; len1 = 0; len2 = 0; } } return 0; }
参考大佬们的动态规划写的 #include<stdio.h> int getSub(char* a, char* b){ int maxLen=0; int n=strlen(a); int m=strlen(b); int dp[1024][1024]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(a[i]==b[j]){ if(i==0||j==0){ dp[i][j]=1; }else{ dp[i][j] = dp[i-1][j-1]+1; } maxLen=maxLen>dp[i][j]?maxLen:dp[i][j]; }else{ dp[i][j]=0; } } } return maxLen; } int main(){ char a[1024]; char b[1024]; int num=0; fgets(a,1024,stdin); fgets(b,1024,stdin); num=getSub(a,b); printf("%d\n",num); }