通过删除字符从现有字符串创建回文

时间:2012-05-14 04:14:25

标签: java string algorithm palindrome

如何通过删除零个或多个字母来确定从单词中获得的最长回文的长度。

例如:amanQQQapl12345anacaZZZnalpaXXXna67890ma
最长的回文将是21位数。

4 个答案:

答案 0 :(得分:8)

这可以通过动态编程来解决。将 d [i,j] 定义为原始字符串中最长回文的长度。

  

如果s [i] = s [j],d [i,j] = max(d [i + 1,j-1] + 2,d [i,j-1],d [i + 1] ,j])。

     

否则d [i,j] = max(d [i,j-1],d [i + 1,j])。

答案 1 :(得分:3)

W中最长的回文是W的longest common subsequence及其镜像。

你可以在O(n²)时间和O(n)空间中计算它,其中n是W的长度但是如果你知道你只需要删除几个字符来制作回文,你就可以有更好的复杂性。

答案 2 :(得分:1)

一个palidrome最多可以有一个奇数计数的字母,即中间字母,以及任意数量的偶​​数字母。

您可以计算每个字母的频率。如果每个字母都不是全部或全部,则为每个字母添加count / 2 * 2,如果任何字母有奇数,则加一个。

答案 3 :(得分:0)

这是@Rambo对答案的正确实施,以防其他人发现他的答案过于简洁。我添加了以前结果的缓存,但条件是不同符号的最大数量最多为1000.由于多个分支使用相同的子分支,这提供了显着的加速。

int d[1000][1000] = {0}; // To store result of previous computation

int computeMaxPalindromeLength(vector<int>& a, int start, int end) {
    if(d[start][end] != 0) // If not precomputed, recompute.
        return d[start][end];
    if(start == end) { // The mid character should be taken as 
        d[start][end] = 1;
        return 1;
    }
    else if(start == end-1) {
        d[start][end] = (a[start] == a[end])?2:1;
        return d[start][end];
    }
    if(a[start] == a[end]) {
        d[start][end] = max( 2 + computeMaxPalindromeLength(a, start+1, end-1), 
            max(computeMaxPalindromeLength(a, start+1, end), computeMaxPalindromeLength(a, start, end-1)));
    } else {
        d[start][end] = max(computeMaxPalindromeLength(a, start+1, end), computeMaxPalindromeLength(a, start, end-1));
    }
    return d[start][end];
}

将上述方法称为: -

vector<int>& a; // Convert each character of string to digit if working with alphanumeric characters.
int maxPalindromeLength = computeMaxPalindromeLength(a, 0, a.size()-1);