动态规划
动态规划,以空间换时间,自底向上求解
计算两字符串的最长公共子序列(可以不连续)
/**
找出 两个 字符串 的公共 子序列(动态规划)
@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);
}
参考链接:
浙公网安备 33010602011771号