Leetcode.1542 找出最长的超赞子字符串

Leetcode.1542 找出最长的超赞子字符串文章讲述了如何使用状态压缩和哈希表的方法解决 LeetCode1542 题 即在给定字符串中找到最长的可以通过字符交换变为回文的子串

大家好,欢迎来到IT知识分享网。

题目链接

Leetcode.1542 找出最长的超赞子字符串 hard

题目描述

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

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

  • 该字符串是 s s s 的一个非空子字符串
  • 进行任意次数的字符交换后,该字符串可以变成一个回文字符串
示例 1:

输入:s = “”
输出:5
解释:“24241” 是最长的超赞子字符串,交换其中的字符后,可以得到回文 “24142”

示例 2:
示例 3:

输入:s = “”
输出:6
解释:“” 是最长的超赞子字符串,交换其中的字符后,可以得到回文 “”

示例 4:
提示:
  • 1 ≤ s . l e n g t h ≤ 1 0 5 1 \leq s.length \leq 10^5 1s.length105
  • s s s 仅由数字组成

解法:状态压缩 + 哈希表

如果一个子串,在进行任意次的字符交换之后,能够变成回文串,说明子串中出现奇数次的字符最多只有一个

又由于 s s s 是由 0 ∼ 9 0 \sim 9 09 的数字组成的,所以我们直接用一个 10 10 10 位的二进制数来表示对应数字字符的出现次数。

  • 如果该位是 0 0 0 ,则说明出现了偶数次;
  • 如果该位是 1 1 1 ,则说明出现了奇数次;

比如 "134" ,对应的二进制数就是 ( 1101 ) 2 = 13 (1101)_2 = 13 (1101)2=13

接着我们使用哈希表来记录其第一次出现的位置(因为我们要求的是最大值,所以只用记录越前面的位置越好,所以直接记录第一次的位置即可)。

我们假设 区间 [ j + 1 , i ] [j + 1,i] [j+1,i]子串 是一个超赞子字符串。

我们用 f f f 表示子串对应的二进制数。

那么 f ( 0 , i ) f(0,i) f(0,i) f ( 0 , j ) f(0,j) f(0,j) 最多只有一位数不同

因为 f ( j , i ) f(j,i) f(j,i) 相当于是 f ( 0 , i ) − f ( 0 , j ) f(0,i) – f(0,j) f(0,i)f(0,j),因为 区间 [ j + 1 , i ] [j + 1,i] [j+1,i]子串 是一个超赞子字符串,那么 f ( j , i ) f(j,i) f(j,i) 最多就只有一位是 1 1 1 ,其他的都是 0 0 0

如此一来,我们就可以分开讨论:

  • f ( 0 , i ) = f ( 0 , j ) f(0,i) = f(0,j) f(0,i)=f(0,j) 的情况;
  • f ( 0 , i ) − f ( 0 , j ) = 1 ′ f(0,i) – f(0,j) = 1′ f(0,i)f(0,j)=1 的情况;

我们用 m a s k mask mask 来记录 区间 [ 0 , i ] [0,i] [0,i] 字符的出现情况。

1.当 f ( 0 , i ) = f ( 0 , j ) f(0,i) = f(0,j) f(0,i)=f(0,j) 的情况;

如果 哈希表 m p mp mp 里有 m a s k mask mask 的记录,那么 j = m p [ m a s k ] j = mp[mask] j=mp[mask],说明 f ( 0 , j ) = f ( 0 , i ) = m a s k f(0,j) = f(0,i) = mask f(0,j)=f(0,i)=mask,即 [ 0 , j ] [0,j] [0,j] [ 0 , i ] [0,i] [0,i] 字符的出现情况一样, [ j + 1 , i ] [j + 1,i] [j+1,i] 就是一个超赞子字符串。 接着再更新答案, a n s = m a x ( a n s , i − j ) ans = max(ans , i – j) ans=max(ans,ij)

否则就说明第一次出现 m a s k mask mask 这样的情况,记录到哈希表中 m p mp mp 中,即 m p [ m a s k ] = i mp[mask] = i mp[mask]=i

2.当 f ( 0 , i ) − f ( 0 , j ) = 1 ′ f(0,i) – f(0,j) = 1′ f(0,i)f(0,j)=1 的情况;

直接从 0 ∼ 9 0 \sim 9 09 枚举与 m a s k mask mask 相差一位的情况,求最大值。逻辑和第一种情况一样。

时间复杂度: O ( n × 10 ) O(n \times 10) O(n×10)

C++代码:

class Solution { 
    public: int longestAwesome(string s) { 
    int n = s.size() , ans = 0; unordered_map<int,int> mp{ 
   { 
   0,-1}}; int mask = 0; for(int i = 0;i < n;i++){ 
    int k = s[i] - '0'; mask ^= (1 << k); auto it = mp.find(mask); //完全匹配 if(it != mp.end()){ 
    auto j = mp[mask]; ans = max(ans , i - j); } else mp[mask] = i; //差了一个字符 for(int p = 0;p < 10;p++){ 
    int t = mask ^ (1 << p); if(mp.find(t) != mp.end()){ 
    auto j = mp[t]; ans = max(ans , i - j); } } } return ans; } }; 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/154511.html

(0)
上一篇 2025-02-25 16:25
下一篇 2025-02-25 16:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信