Count Different Palindromic Subsequences-LintCode

204 篇文章 0 订阅

Given a string S, find the number of different non-empty palindromic subsequences in S, and return that number modulo 10^9 + 7.
A subsequence of a string S is obtained by deleting 0 or more characters from S.
A sequence is palindromic if it is equal to the sequence reversed.
Two sequences A[1], A[2], … and B[1], B[2], … are different if there is some i for which A[i] != B[i].

注意事项

The length of S will be in the range [1, 1000].
Each character S[i] will be in the set {'a', 'b', 'c', 'd'}.

样例

Given S = "bccb", return 6
Explanation: 
The 6 different non-empty palindromic subsequences are b, c, bb, cc, bcb, bccb.
Note that bcb is counted only once, even though it occurs twice.

Given S = "abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba" return 104860361
Explanation: 
There are 3104860382 different non-empty palindromic subsequences, which is 104860361 modulo 10^9 + 7.
#ifndef C738_H
#define C738_H
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
    /**
    * @param str: a string S
    * @return: the number of different non-empty palindromic subsequences in S
    */
    int countPalindSubseq(string &str) {
        // write your code here
        if (str.empty())
            return 0;
        int len = str.size();
        vector<vector<int>> dic(4, vector<int>());//存储a,b,c,d出现的位置
        vector<vector<int>> nums(len + 1, vector<int>(len + 1, 0));
        for (int i = 0; i < len; ++i)
            dic[str[i] - 'a'].push_back(i);
        return helper(str, dic, nums, 0, len);
    }
    int helper(string &str, vector<vector<int>> dic, vector<vector<int>> &nums, int start, int end)
    {
        if (start >= end)
            return 0;
        if (nums[start][end] > 0)//表示当前位置已经计算过
            return nums[start][end];
        long long res = 0;
        for (int i = 0; i < dic.size(); ++i)
        {
            if (dic[i].empty())//表示字母在对应的数组中没有值
                continue;
            //查找第一个不小于start的位置和第一个小于end的位置
            auto it_start = lower_bound(dic[i].begin(), dic[i].end(), start);
            auto it_end = lower_bound(dic[i].begin(), dic[i].end(), end) - 1;
            //若当前区间内没有此字母
            if (it_start == dic[i].end() || *it_start >= end)
                continue;
            res++;
            //若it_start,it_end指向不同的字母
            if (it_start != it_end)
                res++;
            res += helper(str, dic, nums, *it_start + 1, *it_end);
        }
        //为防止超出范围,取余
        nums[start][end] = res % (int)(1e9 + 7);
        return nums[start][end];
    }
};
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值