【发布时间】:2015-08-08 14:20:21
【问题描述】:
假设字符串是“anuja”,输出应该是 2,因为如果我删除字符 'u' 和 'n',给定的字符串变成回文。因此输出应该是最小的删除次数。 更多示例:输入字符串:“ababa” 输出:0(无需移除) 输入字符串:“abcdba” 输出:1(删除“c”或“d”) 请解释一下算法。
【问题讨论】:
-
不错的问题。到目前为止,您尝试了什么?您的解决方案有什么问题?
假设字符串是“anuja”,输出应该是 2,因为如果我删除字符 'u' 和 'n',给定的字符串变成回文。因此输出应该是最小的删除次数。 更多示例:输入字符串:“ababa” 输出:0(无需移除) 输入字符串:“abcdba” 输出:1(删除“c”或“d”) 请解释一下算法。
【问题讨论】:
让dp[i, j] = minimum number of removals needed to convert the substring [i, j] to a palindrome。我们有:
dp[i, i] = 0 for all i (every single character is a palindrome)
要找到dp[i, j],让我们考虑一个随机字符串。我们有两种可能:
第一个和最后一个字符相等:a[i] == a[j]。在这种情况下,我们可以将问题简化为找到需要删除的最小字符数,以使子字符串[i+1, j-1] 成为回文。
第一个和最后一个字符不相等:a[i] != a[j]。在这种情况下,我们需要删除其中一个。我们将删除导致我们找到更好解决方案的内容。
所以我们有:
dp[i, j] = dp[i + 1, j - 1] # if a[i] == a[j]
min(dp[i + 1, j], dp[i, j - 1]) + 1 # otherwise
以anuja 为例。我们会得到:
| 1 2 3 4 5
-------------
1 | 0 1 2 2 2
2 | 0 1 2 3
3 | 0 1 2
4 | 0 1
5 | 0
请注意,矩阵是从主对角线开始计算的,然后依次向上计算,对角线平行于主对角线。答案是dp[1, n]。
这类似于Levenshtein distance,但它只考虑删除。
【讨论】:
^) 对其进行投票。
您可以测量从字符串到其反向(忽略替换)的编辑距离(levenshtein 距离)。所需的值将是该值的一半。
这个问题类似于UVA 10739。这是example implementation。
一个示例实现(适用于您的情况)可以是:
string P, Q;
getline(cin, P);
Q = string(P.rbegin(), P.rend());
int p = P.size(), q = Q.size();
for(int i=0; i<=p; i++) { T[i][0] = i; }
for(int i=0; i<=q; i++) { T[0][i] = i; }
for(int i=1; i<=p; i++) {
for(int j=1; j<=q; j++) {
if (P[i-1] == Q[j-1])
T[i][j] = T[i-1][j-1];
else
T[i][j] = min(T[i-1][j], T[i][j-1]) + 1;
}
}
cout << "Case " << tt << ": " << T[p][q]/2 << endl;
【讨论】: