【贪心】【回溯】【字符串】2014. 重复 K 次的最长子序列

本文涉及知识点

贪心 回溯 字符串

LeetCode2014. 重复 K 次的最长子序列

给你一个长度为 n 的字符串 s ,和一个整数 k 。请你找出字符串 s 中 重复 k 次的 最长子序列 。

子序列 是由其他字符串删除某些(或不删除)字符派生而来的一个字符串。

如果 seq * k 是 s 的一个子序列,其中 seq * k 表示一个由 seq 串联 k 次构造的字符串,那么就称 seq 是字符串 s 中一个 重复 k 次 的子序列。

举个例子,"bba" 是字符串 "bababcba" 中的一个重复 2 次的子序列,因为字符串 "bbabba" 是由 "bba" 串联 2 次构造的,而 "bbabba" 是字符串 "bababcba" 的一个子序列。

返回字符串 s 中 重复 k 次的最长子序列 。如果存在多个满足的子序列,则返回 字典序最大 的那个。如果不存在这样的子序列,返回一个 空 字符串。

示例 1:

example 1

输入:s = "letsleetcode", k = 2

输出:"let"

解释:存在两个最长子序列重复 2 次:let" 和 "ete" 。

"let" 是其中字典序最大的一个。

示例 2:

输入:s = "bb", k = 2

输出:"b"

解释:重复 2 次的最长子序列是 "b" 。

示例 3:

输入:s = "ab", k = 2

输出:""

解释:不存在重复 2 次的最长子序列。返回空字符串。

提示:

n == s.length

2 <= k <= 2000

2 <= n < k * 8

s 由小写英文字母组成

回溯

因为n < k*8, 则最多7个字符。

string s1 记录 出现数量>=k次的字符。如果一个字符出现m × \times ×k次,则记录m次。

枚举mask ∈ \in ∈ 1,1 \<\< s1.length()

for(int i= 0 ; i < s1.length();i++ )

{

if(mask&(1<<i))

{

s2 += s1i;

}

}

将s2 降序排序,计算是否存在k个为s2的子序列。如果有,直接返回;否则,用系统函数prev_permutation计算前一个字典序。

代码

核心代码

cpp 复制代码
class Solution {
public:
	string longestSubsequenceRepeatedK(string s, int k) {
		m_s = s;
		m_iK = k;
		int cnt[26] = { 0 };
		for (const auto& ch : s)
		{
			cnt[ch - 'a']++;
		}
		string s1;
		for (int i = 0; i < 26; i++)
		{
			s1 += string(cnt[i] / k, 'a' + i);
		}
		const int n = s1.length();
		for (int i = 1; i < (1 << n); i++)
		{
			string s2;
			for (int j = 0; j < n; j++)
			{
				if (i & (1 << j))
				{
					s2 += s1[j];
				}
			}
			Do(s2);
		}
		return m_res.empty() ? "" : m_res.rbegin()->second;
	}
	void Do(string& s2)
	{
		sort(s2.begin(), s2.end(), std::greater<>());
		do
		{
			int cnt = 0;
			for (const auto& ch : m_s)
			{
				if (ch == s2[cnt % s2.length()])
				{
					cnt++;
				}
			}
			if (cnt >= m_iK * s2.length())
			{
				m_res.emplace(s2.length(), s2);
				if (m_res.size() > 1)
				{
					m_res.erase(m_res.begin());
				}
			}
		} while (prev_permutation(s2.begin(), s2.end()));
	}
	set<pair<int, string>> m_res;
	string m_s;
	int m_iK;
};

2023年5月版

class Solution {

public:

string longestSubsequenceRepeatedK(string s, int k) {

m_s = s;

m_c = s.length();

m_iK = k;

m_vFreq.resize(26);

for (const char&ch : s)

{

m_vFreqch - 'a'++;

}

for (int len = 7; len > 0; len--)

{

string str = dfs("", len);

if (str.length())

{

return str;

}

}

return "";

}

string dfs(string str,int leve)

{

if (0 == leve)

{

return Do(str)?str:"";

}

for (int i = 25; i >= 0; i--)

{

if (m_vFreqi < m_iK)

{

continue;

}

m_vFreqi -= m_iK;

string strRet = dfs(str + char(i + 'a'), leve - 1);

if (strRet.length())

{

return strRet;

}

m_vFreqi += m_iK;

}

return "";

}

bool Do(const string& strSub)

{

int iSBegin = 0;

int i = 0, k =0;

for (; iSBegin < m_c; iSBegin++)

{

if (strSubi == m_siSBegin)

{

i++;

}

if (strSub.length() == i)

{

i = 0;

k++;

}

if (m_iK == k)

{

return true;

}

}

return false;

}

int m_c;

string m_s;

int m_iK;

vector m_vFreq;

};

2023年7月

class Solution {

public:

string longestSubsequenceRepeatedK(string s, int k) {

m_c = s.length();

m_iK = k;

m_s = s;

m_vNums.assign(m_c+1, vector(26));

/*

for (int i = m_c - 1; i >= 0; i--)

{

m_vNumsi = m_vNumsi + 1;

m_vNumsis\[i - 'a']++;

}
/
for (int i = 0; i < m_c; i++)
{
m_vIndexss\[i - 'a'].emplace_back(i);
}
vector cur;
int aUse26 = { 0 };
dfs(cur, aUse, 0);
return m_strRet;
}
void dfs(vector& cur,int
aUse, int iCurIndex)

{

for (int i = 0; i < 26; i++)

{

const auto& v = m_vIndexsi;

int index = std::lower_bound(v.begin(), v.end(), iCurIndex) - v.begin();

if (index >= v.size())

{

continue;

}

cur.push_back(i);

aUsei++;

if (Check(cur, aUse, vindex + 1))

{

dfs(cur, aUse, vindex + 1);

}

cur.pop_back();

aUsei--;

}

}

bool Check(const vector& cur, int* aUse, int iCurIndex)

{

for (int i = 1; i < m_iK; i++)

{

for (const auto& ch : cur)

{

const auto& v = m_vIndexsch;

int index = std::lower_bound(v.begin(), v.end(), iCurIndex) - v.begin();

if (index >= v.size())

{

return false;

}

iCurIndex = vindex + 1;

}

}

string ret;

for (const auto& tmp : cur)

{

ret += 'a' + tmp;

}

if (ret.length() > m_strRet.length())

{

m_strRet = ret;

}

else if (ret.length() == m_strRet.length())

{

if (ret > m_strRet)

{

m_strRet = ret;

}

}

return true;

}

int m_c;

vector<vector> m_vNums;

std::vector m_vIndexs26;

int m_iK;

string m_s;

string m_strRet;

};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关推荐
林爷万福6 分钟前
光谱数据预处理:基线校正、平滑去噪实战
人工智能·算法
8Qi819 分钟前
LeetCode 1049:最后一块石头的重量 II —— 题解 ✅
算法·leetcode·职场和发展·动态规划·01背包
wuminyu32 分钟前
Java锁机制之Java对象重量级锁源码剖析
java·linux·c语言·jvm·c++
wubba lubba dub dub75034 分钟前
第四十九周学习周报
人工智能·算法·机器学习
Java_2017_csdn1 小时前
ComplexKeysShardingAlgorithm 小结
java·大数据·算法
海梨花1 小时前
快手面试高频算法题
java·算法·面试
lqqjuly1 小时前
超分辨率算法深度解析(Super-Resolution Algorithms)
算法
郝学胜_神的一滴1 小时前
Qt 高级开发 026:QTabWidget御道,从筑基到化境
c++·qt
apocelipes2 小时前
GNU GCC 多版本函数扩展
c语言·c++·linux编程
代码中介商2 小时前
C++完美转发与引用折叠全解析
开发语言·c++