动态规划,以空间换时间,自底向上求解
计算两字符串的最长公共子序列(可以不连续)
/** 找出 两个 字符串 的公共 子序列(动态规划) @param str1 字符串1 @param str2 字符串2 */ void maxPublicSubSequence(char *str1, char *str2) { assert(str1 != NULL && str2 != NULL); // 字符串 1 长度 int str1Length = strlen(str1); // 字符串 2 长度 int str2Length = strlen(str2); // 开辟 二维 存储 数组 (并初始化 值为:0) int **postionArray = (int **)malloc(sizeof(int *) * (str1Length + 1)); for (int i = 0; i <= str1Length; i ++) { postionArray[i] = (int *)malloc(sizeof(int) * (str2Length + 1)); } for (int i = 0; i <= str1Length; i++) { for (int j = 0; j <= str2Length; j++) { postionArray[i][j] = 0; } } // 循环 遍历 for(int i = 1; i <= str1Length; i++) { for(int j = 1; j <= str2Length; j ++) { // 如果 两个字符 相同 if (str1[i - 1] == str2[j - 1]) { postionArray[i][j] = postionArray[i - 1][j - 1] + 1; } // 如果 两个 字符 不同 else { postionArray[i][j] = (postionArray[i - 1][j] > postionArray[i][j - 1]) ? postionArray[i - 1][j] : postionArray[i][j - 1]; } } } for (int i = 0; i < str1Length; i++) { for (int j = 0; j < str2Length; j++) { printf("%d ", postionArray[i][j]); } printf("\n"); } int i, j ; for (i = str1Length, j = str2Length; i >= 1 && j >= 1;) { if (str1[i - 1] == str2[j - 1]) { printf("%c ", str1[i - 1]); i --; j --; } else { if (postionArray[i][j - 1] > postionArray[i - 1][j]) { j--; } else { i --; } } } // 释放开辟数组 for (int i = 0; i < str1Length; i++) { free(postionArray[i]); } free(postionArray); } int main(int argc, const char * argv[]) { @autoreleasepool { maxPublicSubSequenceTwo("ABCBDAB" , "BDCABA"); } return 0; }
给定两个字符串,求出它们之间最长的相同子字符串的长度。
穷举法:
#import <Foundation/Foundation.h> /** 找出 两个 字符串 的 最长 公共 子串 (穷举法) @param str1 字符串1 @param str2 字符串2 */ void maxPublicSubStringOne(char *str1, char *str2) { assert(str1 != NULL && str2 != NULL); // 起始 位置 int startPosition = 0; // 公共 子串 长度 int maxStringLength = 0; // 循环 遍历 所有 子字符串 for (int i = 0; i < strlen(str1); i ++) { for (int j = 0; j < strlen(str2); j++) { // 如果 两个 字符 相等 if(str1[i] == str2[j]) { // 继续 比较 后面的字符 int k = 1; while (str1[i + k] == str2[j + k] && str1[i + k] != '\0' && str2[j + k] != '\0') { k ++; } // 如果 k 大于 最长 字符串 if (k > maxStringLength) { // 公共 子串 长度 maxStringLength = k; // 起始位置 startPosition = i; } } } } if(maxStringLength > 0) { for (int i = startPosition; i <= maxStringLength; i++) { printf("%c ", str1[i]); } } }
动态规划法
/** 找出 两个 字符串 的公共 子串(动态规划) @param str1 字符串1 @param str2 字符串2 */ void maxPublicSubStringTwo(char *str1, char *str2) { assert(str1 != NULL && str2 != NULL); // 起始 位置 int startPosition = 0; // 公共 子串 长度 int maxStringLength = 0; // 字符串 1 长度 int str1Length = strlen(str1); // 字符串 2 长度 int str2Length = strlen(str2); // 开辟 二维 存储 数组 (并初始化 值为:0) int **postionArray = (int **)malloc(sizeof(int *) * str1Length); for (int i = 0; i < str1Length; i ++) { postionArray[i] = (int *)malloc(sizeof(int) * str2Length); } for (int i = 0; i < str1Length; i++) { for (int j = 0; j < str2Length; j++) { postionArray[i][j] = 0; } } // 循环 遍历 for(int i = 0; i < str1Length; i++) { for(int j = 0; j < str2Length; j ++) { // 如果 两个字符 相同 if (str1[i] == str2[j]) { // 判断 释放 是 边界 情况 if (i == 0 || j == 0) { // 边界 情况 postionArray[i][j] = 1; } // 非边界 情况 else { postionArray[i][j] = postionArray[i - 1][j - 1] + 1; } if (postionArray[i][j] > maxStringLength) { maxStringLength = postionArray[i][j]; startPosition = i - postionArray[i][j] + 1; } } } } // 打印 字符串 if(maxStringLength > 0) { for (int i = 0; i <= maxStringLength; i++) { printf("%c ", str1[startPosition + i]); } } // 释放开辟数组 for (int i = 0; i < str1Length; i++) { free(postionArray[i]); } free(postionArray); }
参考链接: