[Leetcode]5869. 两个回文子序列长度的最大乘积

【题目描述如下】

给你一个字符串 s ,请你找到 s 中两个 不相交回文子序列 ,使得它们长度的 乘积最大 。两个子序列在原字符串中如果没有任何相同下标的字符,则它们是 不相交 的。

请你返回两个回文子序列长度可以达到的 最大乘积 。

子序列 指的是从原字符串中删除若干个字符(可以一个也不删除)后,剩余字符不改变顺序而得到的结果。如果一个字符串从前往后读和从后往前读一模一样,那么这个字符串是一个 回文字符串 。

 【分析】

从提示来看,数据量不大,但是字符串的组合很多,每个字符都有选和不选两种情况,最大有1 << 12 - 1个子串,需要对每个子串进行是否为回文串的判断。

可以采用状态压缩来做,用二进制位标记每个字符的选与不选,遍历整个状态空间,枚举所有字符串;

针对每个字符串,对其补集的子集进行遍历;

【代码如下】

class Solution {
public:
    /*
        由于数据量不大,可以枚举所有的状态空间,使用二进制表示的方式进行状态压缩,
每个二进制位标志字符串中的每个字符;
    */
    bool IsPal(string& s)
    {
        int i = 0;
        int j = s.size() - 1;
        while (i < j) {
            if (s[i++] != s[j--]) {
                return false;
            }
        }
        return true;
    }
    int maxProduct(string s) {
        int res = 0;
        int n = s.size();
        bool allSubStr[1 << 12] {false};
        int subStrLen[1 << 12] {0};
        for (int i = 1; i < 1 << n; i++) {
            string subStr;
            for (int j = 0; j < n; j++) {
                if ((i >> j) & 0x1) {
                    subStr.push_back(s[j]);
                }
            }
            if (IsPal(subStr)) {
                allSubStr[i] = true;
                subStrLen[i] = subStr.size();
            }
        }
        for (int i = 1; i < 1 << n; i++) {
            if (!allSubStr[i]) {
                continue;
            };
            // 求补集,枚举补集的所有子集,采用l = (l - 1) & left遍历子集
            int left = i ^ ((1 << n) - 1);
            for (int l = left; l != 0; l = (l - 1) & left) {
                if (allSubStr[l]) {
                    res = max(res, subStrLen[i] * subStrLen[l]);
                }  
            }
        }
        return res;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值