https://leetcode-cn.com/problems/find-longest-awesome-substring/
题意:
给你一个字符串 s 。请返回 s 中最长的 超赞子字符串 的长度。
「超赞子字符串」需满足满足下述两个条件:
该字符串是 s 的一个非空子字符串
进行任意次数的字符交换后,该字符串可以变成一个回文字符串
方法:哈希表+前缀和,主要在于够建状态哈希表,和哈希表映射操作来进行状态的转换,利用异或的性质,一个数经过两次异或以后,会得到自己本身的值,但是映射操作无法获取由一个出现奇数次的数字和数个出现偶数次的数字组成的数字串,需要通过循环,进行额外的判断。
class Solution {
public:
int longestAwesome(string s) {
int maxL=0;
vector<int> v1(1024,-2);//哈希表
vector<int> v2={1,2,4,8,16,32,64,128,256,512};//存储状态映射操作关系
v1[0]=-1;//初始化0状态对应的序列号为-1
int cur = 0;//初始化状态为0
for(int i=0;i<s.size();i++)
{
cur^=v2[s[i]-'0'];//选择对应的状态的操作,如果是数字0,我们选择v2[0],与1异或,如果是数字1,我们选择v2[1],与2异或
if(v1[cur]==-2)//如果对应的状态不存在哈希表,将状态对应的序列号写入哈希表
v1[cur] = i;
else//否则我们就看看最大值能不能更新
maxL = maxL>(i-v1[cur])?maxL:(i-v1[cur]);
for(int j=0;j<10;j++)//这一步是因为以上的操作只能过选择数字出现次数为偶数次的数字串,加上这一步就能获得出现偶数次的数字和一个出现奇数次的数字组合起来的数字串
{
int tmp = cur;
tmp ^= v2[j];
if(v1[tmp]!=-2)
maxL = maxL>(i-v1[tmp])?maxL:(i-v1[tmp]);
}
}
return maxL;
}
};
优化后的代码:
class Solution {
public:
int longestAwesome(string s) {
int maxL=0;
vector<int> v1(1024,-2);
v1[0]=-1;
int cur = 0;
for(int i=0;i<s.size();i++)
{
cur^=1<<(s[i]-'0');
if(v1[cur]==-2)
v1[cur] = i;
else
maxL = maxL>(i-v1[cur])?maxL:(i-v1[cur]);
for(int j=0;j<10;j++)
{
int tmp = cur;
tmp ^= 1<<j;
if(v1[tmp]!=-2)
maxL = maxL>(i-v1[tmp])?maxL:(i-v1[tmp]);
}
}
return maxL;
}
};