【dp状态压缩】leetcode1542. 找出最长的超赞子字符串

题目

给你一个字符串 s 。请返回 s 中最长的 超赞子字符串 的长度。

「超赞子字符串」需满足满足下述两个条件:

  1. 该字符串是 s 的一个非空子字符串
  2. 进行任意次数的字符交换后,该字符串可以变成一个回文字符串
实例1:
	输入:s = "3242415"
	输出:5
	解释:"24241" 是最长的超赞子字符串,交换其中的字符后,可以得到回文 "24142"

实例2:
	输入:s = "12345678"
	输出:1

实例3:
	输入:s = "213123"
	输出:6
	解释:"213123" 是最长的超赞子字符串,交换其中的字符后,可以得到回文 "231132"

实例4:
	输入:s = "00"
	输出:2

思路

这道题看题解也断断续续理解了好几天,状态压缩都忘得差不多了
步骤:

  1. 形成超赞字符串只有2种情况:①所有数字的个数都是偶数 ②只有一个数字的个数是奇数
  2. 用二进制位运算进行状态压缩,从右往左表示每个数字的数量的奇偶情况(为1表示数字的数量为奇数,为0表示数字的数量为偶数,例如两个1的时候,1^1=0,因此用0表示偶数,1表示奇数。)
  3. 用dp数组记录下每个二进制压缩状态最先出现的位置,后面如果再出现该状态,表示这是一个回文串(因为所有的数字又重复出现了一遍才会导致后面的状态和前面的状态相同),长度为i-dp[str](对应①所有数字的个数都是偶数)
  4. 尝试改变一个数字(0-9)的数量,查看改变后的状态是否存在,若存在,表示这也是一个回文串(对应 ②只有一个数字的个数是奇数)

代码

class Solution {
public:
    int longestAwesome(string s) {
        int ans = 0, str = 0, n = s.size(); //str记录状态
        vector<int> dp(1<<10, INT_MAX);
        dp[str] = -1;	//状态为0证明所有数字都出现了偶数遍
        for(int i=0; i<n; i++){
            str ^= (1<<(s[i]-'0'));

            //只有一个数字不同(奇数)
            for(int j=0; j<10; j++){
                int tmp = str^(1<<j);
                ans = max(ans, i-dp[tmp]);      
            }

            //偶数
            //若该状态未出现过,记录最开始的位置
            if(dp[str]==INT_MAX)
                dp[str] = i;
            else //该状态出现过了,则计算i-dp[str]未回文串长度
                ans = max(ans, i-dp[str]);
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值