计算在已知字符串中所有回文子序列的数目

原文地址:Count All Palindromic Subsequence in a given String

在已知的字符串中查找有多少个回文的子序列(没必要对相同的做区分)。注意空字符串不能看作是回文。

例子:

输入 : str = "abcd"
输出 : 4
解释 :- 回文子序列有 : "a" ,"b", "c" ,"d" 

输入 : str = "aab"
输出 : 4
解释 :- 回文子序列有 :"a", "a", "b", "aa"

输入 : str = "aaaa"
输出 : 15

以上问题可以做递归定义。

初始化 : i= 0, j= n-1;

CountPS(i,j)
// 一个字符串中每个单一的字符都是回文的子序列
if i == j
   return 1 // 回文的长度是1

// 如果首位字符相同, 那么我们就认为它是一个回文子序列, 并检查剩下的序列(i+1, j), (i, j-1)
Else if (str[i] == str[j)]
   return   countPS(i+1, j) + countPS(i, j-1) + 1;

else
   // 当计算countPS(i+1, j) + countPS(i,j-1)的时候,检查剩下的子序列并移除一般的回文子序列因为它们计算了两次
   return countPS(i+1, j) + countPS(i, j-1) - countPS(i+1, j-1) 

如果我们画一下以上递归方法的递归树,我们可以看到有重复的子问题。因为问题有重复子问题,那么我们就可以用动态规划来解决它。下面是基于动态规划的实现:

// Counts Palindromic Subsequence in a given String
#include<iostream>
#include<cstring>
using namespace std;

// Function return the total palindromic subsequence
int countPS(string str)
{
    int N = str.length();

    // create a 2D array to store the count of palindromic
    // subsequence
    int cps[N+1][N+1];
    memset(cps, 0 ,sizeof(cps));

    // palindromic subsequence of length 1
    for (int i=0; i<N; i++)
        cps[i][i] = 1;

    // check subsequence of length L is palindrome or not
    for (int L=2; L<=N; L++)
    {
        for (int i=0; i<N; i++)
        {
            int k = L+i-1;
            if (str[i] == str[k])
                cps[i][k] = cps[i][k-1] +
                            cps[i+1][k] + 1;
            else
                cps[i][k] = cps[i][k-1] +
                            cps[i+1][k] -
                            cps[i+1][k-1];
        }
    }

    // return total palindromic subsequence
    return cps[0][N-1];
}

// Driver program
int main()
{
    string str = "abcb";
    cout << "Total palindromic subsequence are : "
         << countPS(str) << endl;
    return 0;
}

输出:

Total palindromic subsequence are : 6

时间复杂度:O( N2 )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值