
给你一个字符串 s ,请你找到 s 中两个 不相交回文子序列 ,使得它们长度的 乘积最大 。 两个子序列在原字符串中如果没有任何相同下标的字符,则它们是 不相交 的。
请你返回两个回文子序列长度可以达到的 最大乘积 。
子序列 指的是从原字符串中删除若干个字符(可以一个也不删除)后,剩余字符不改变顺序而得到的结果。如果一个字符串从前往后读和从后往前读一模一样,那么这个字符串是一个 回文字符串 。
示例 1:

输入:s = "leetcodecom"
输出:9
解释:最优方案是选择 "ete" 作为第一个子序列,"cdc" 作为第二个子序列。
它们的乘积为 3 * 3 = 9 。
示例 2:
输入:s = "bb"
输出:1
解释:最优方案为选择 "b" (第一个字符)作为第一个子序列,"b" (第二个字符)作为第二个子序列。
它们的乘积为 1 * 1 = 1 。
示例 3:
输入:s = "accbcaxxcxx"
输出:25
解释:最优方案为选择 "accca" 作为第一个子序列,"xxcxx" 作为第二个子序列。
它们的乘积为 5 * 5 = 25 。
提示:
2 <= s.length <= 12
s 只含有小写英文字母。来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximum-product-of-the-length-of-two-palindromic-subsequences 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
类似题目:LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)
226 / 226 个通过测试用例
class Solution {
public:
int maxProduct(string s) {
int n = s.size();
int ans = 1, state = (1<<n)-1;
for(int i = state; i; i=state&(i-1))
{
int left = ~i&state;
for(int k = left; k; k=left&(k-1))
ans = max(ans, process(s, i)*process(s, k));
}
return ans;
}
int process(string& s, int num)
{
int n = s.size();
string t;
for(int i = 0; i < n; ++i)
{
if(num&(1<<i))
t.push_back(s[i]);
}
int ans = 0, i = 0, j = int(t.size())-1;
while(i < j)
{
if(t[i] == t[j])
{
i++, j--;
ans += 2;
}
else
break;
}
if(i < j) return 0;
if(i == j) return ans+1;
else return ans;
}
};对于判断是否是回文的操作预先进行处理
class Solution {
public:
int maxProduct(string s) {
int n = s.size();
vector<int> palind = process(s);
int ans = 1, state = (1<<n)-1;
for(int i = state; i; i=state&(i-1))
{
int left = ~i&state;
for(int k = left; k; k=left&(k-1))
ans = max(ans, palind[i]*palind[k]);
}
return ans;
}
vector<int> process(string& s)
{
int n = s.size();
vector<int> palind(1<<n, 0);
for(int state = (1<<n)-1; state; state--)
{
string t;
for(int i = 0; i < n; ++i)
{
if(state&(1<<i))
t.push_back(s[i]);
}
int ans = 0, i = 0, j = int(t.size())-1;
while(i < j)
{
if(t[i] == t[j])
{
i++, j--;
ans += 2;
}
else
break;
}
if(i < j) ;
if(i == j) palind[state] = ans+1;
else palind[state] = ans;
}
return palind;
}
};128 ms 7.1 MB C++