C程序查找形成回文的最小插入次数

什么是回文

回文是指正向和反向拼写相同的单词、词组、数字或其他字符序列。例如,"racecar"就是一个回文。

问题背景

给定一个字符串,通过插入最少的字符使它变成一个回文序列。例如,对于字符串"AACECAAAA",所需的最小插入次数为2,结果为"AAACECAAAA"。

动态规划求解

定义状态

我们可以定义一个二维数组dp来表示从i到j的最少插入次数,其中i和j分别表示字符串的起始位置和结束位置。

状态转移方程

如果s[i] == s[j],那么dp[i][j] = dp[i + 1][j - 1]。

如果s[i] != s[j],那么dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1。

边界条件

对于单个字符,它本身就是一个回文序列,因此dp[i][i] = 0。

代码实现

下面是使用动态规划求解的代码实现:

int minInsertions(string s) {

int n = s.size();

vector<vector<int>> dp(n, vector<int>(n, 0));

for (int i = n - 2; i >= 0; --i) {

for (int j = i + 1; j < n; ++j) {

if (s[i] == s[j]) {

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

} else {

dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;

}

}

}

return dp[0][n - 1];

}

按照题目要求进行修改

按照题目要求,最小插入次数不应该返回,而是应该返回插入后的回文字符串。在动态规划中加入一个二维数组path,用于记录每个状态的路径。

代码实现

下面是修改后的代码实现:

string minInsertions(string s) {

int n = s.size();

vector<vector<int>> dp(n, vector<int>(n, 0));

vector<vector<string>> path(n, vector<string>(n, ""));

for (int i = n - 2; i >= 0; --i) {

for (int j = i + 1; j < n; ++j) {

if (s[i] == s[j]) {

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

path[i][j] = s[i] + path[i + 1][j - 1] + s[j];

} else {

if (dp[i + 1][j] < dp[i][j - 1]) {

dp[i][j] = dp[i + 1][j] + 1;

path[i][j] = s[i] + path[i + 1][j] + s[i];

} else {

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

path[i][j] = s[j] + path[i][j - 1] + s[j];

}

}

}

}

return path[0][n - 1];

}

总结

这篇文章介绍了使用动态规划算法求解最小插入次数的方法,同时还对题目要求进行了修改,返回了插入后的回文字符串。使用动态规划算法可以在O(n^2)的时间复杂度内解决该问题。

后端开发标签