C++算法:包含三个字符串的最短字符串

简介: C++算法:包含三个字符串的最短字符串

涉及知识点

有序集合 字符串

题目

给你三个字符串 a ,b 和 c , 你的任务是找到长度 最短 的字符串,且这三个字符串都是它的 子字符串

如果有多个这样的字符串,请你返回 字典序最小 的一个。

请你返回满足题目要求的字符串。

注意:

两个长度相同的字符串 a 和 b ,如果在第一个不相同的字符处,a 的字母在字母表中比 b 的字母 靠前 ,那么字符串 a 比字符串 b 字典序小 。

子字符串 是一个字符串中一段连续的字符序列。

示例 1:

输入:a = “abc”, b = “bca”, c = “aaa”

输出:“aaabca”

解释:字符串 “aaabca” 包含所有三个字符串:a = ans[2…4] ,b = ans[3…5] ,c = ans[0…2] 。结果字符串的长度至少为 6 ,且"aaabca" 是字典序最小的一个。

示例 2:

输入:a = “ab”, b = “ba”, c = “aba”

输出:“aba”

解释:字符串 “aba” 包含所有三个字符串:a = ans[0…1] ,b = ans[1…2] ,c = ans[0…2] 。由于 c 的长度为 3 ,结果字符串的长度至少为 3 。“aba” 是字典序最小的一个。

参数范围

1 <= a.length, b.length, c.length <= 100

a ,b ,c 只包含小写英文字母。

分析

合并两个字符串

假定a在前,b在后。有如下两种情况。

a包括b a=“ab”,b=“a”,合并后为"ab"
a的后缀和b的前缀相同,以下简称公共后前缀 a=“ab”,b=“bc”,合并后"abc"

分两部

第一步 第二步
ab abc
ab c(ab)
ac acb
ac b(ac)
ba bac
ba c(ba)
bc bca
bc a(bc)
ca cab
ca b(ca)
cb cba
cb a(cb)
共12种情况

abc和a(bc)相同

abc和a(bc)相比,效果相同或更好,所以无需考虑a(bc)等。

bc是第一种情况 abc就是ab,a(bc)也是
ab是第一种情况 这种情况不符合,abc=ac a(bc)等于a(xc),如果xc是的前缀是a的后缀,且比x长,那c也是后缀,两者节省的长度相同。如果xc的前缀不是a的后缀,则c的前缀有可能是a的后缀,这种情况下:abc优于a(bc)。
ab和bc都是第二种情况 abc = a减去ab公共后前缀+b+c减去bc公共后前缀 a(bc)也是

变量函数解释

m_setStrs 记录备选答案,自动根据长度和字典序排序
next_permutation 下一个顺序,初始要排序,使得初始最小序

代码

class Solution {
public:
  string minimumString(string a, string b, string c) {
    vector<string> strs = { a,b,c };
    sort(strs.begin(), strs.end());
    do
    {
      string tmp = Union(strs[0], strs[1]);
      tmp = Union(tmp, strs[2]);
      m_setStrs.emplace(tmp.length(), tmp);
    } while (next_permutation(strs.begin(), strs.end()));
    return m_setStrs.begin()->second;
  }
  string Union(const string& a, const string& b)
  {
    if (-1 != a.find(b))
    {
      return a;
    }
    int len = min(a.length(), b.length());
    int i = len;
    for (; i > 0; i--)
    {
      if (a.substr(a.length() - i) == b.substr(0, i))
      {
        break;
      }
    }
    return a.substr(0, a.length() - i) + b;
  }
  std::set<std::pair<int, string>> m_setStrs;
};

旧版代码

class Solution {
public:
string minimumString(string a, string b, string c) {
vector strs = { a,b,c };
sort(strs.begin(), strs.end());
if (-1 != strs[1].find(strs[0]))
{
strs[0] = “”;
}
if (-1 != strs[2].find(strs[1]))
{
strs[1] = “”;
}
do
{
Union(strs[0], strs[1], strs[2]);
} while (next_permutation(strs.begin(), strs.end()));
return m_setStrs.begin()->second;
}
void Union(const string& a, const string& b, const string& c)
{
string tmp = Union(a, b);
tmp = Union(tmp, c);
m_setStrs.emplace(tmp.length(), tmp);
}
string Union(const string& a, const string& b)
{
if (-1 != a.find(b))
{
return a;
}
int len = min(a.length(), b.length());
int i = len;
for (; i > 0; i–)
{
if (a.substr(a.length()-i)== b.substr(0,i))
{
break;
}
}
return a.substr(0, a.length() - i) + b;
}
std::set<std::pair<int, string>> m_setStrs;
};

旧版代码二

class Solution {
public:
string minimumString(string a, string b, string c) {
Union(a, b, c);
Union(a, c, b);
Union(b, a, c);
Union(b, c, a);
Union(c, a, b);
Union(c, b, a);
return m_setStrs.begin()->second;
}
void Union(const string& a, const string& b,const string& c)
{
string tmp = Union(a, b);
tmp = Union(tmp, c);
m_setStrs.emplace(tmp.length(),tmp);
tmp = Union(b, c);
tmp = Union(a, tmp);
m_setStrs.emplace(tmp.length(), tmp);
}
string Union(const string& a, const string& b)
{
if (-1 != a.find(b))
{
return a;
}
int len = min(a.length(), b.length());
int i = len;
for (; i > 0; i–)
{
if (Same(a, b, i))
{
break;
}
}
return a.substr(0, a.length() - i) + b;
}
bool Same(const string& a, const string& b, int len)
{
for (int i = 0; i < len; i++)
{
if (a[a.length() - len + i] != b[i])
{
return false;
}
}
return true;
}
std::set<std::pair<int,string>> m_setStrs;
};

2023年8月份代码

class Solution {
public:
string minimumString(string a, string b, string c) {
Cat(a, b, c);
Cat(a, c, b);
Cat(b, a, c);
Cat(b, c, a);
Cat(c, a, b);
Cat(c, b, a);
string strRet = *m_setCan.begin();
for (const auto& it : m_setCan )
{
if (it.length() < strRet.length())
{
strRet = it;
}
}
return strRet;
}
void Cat(string a, string b, string c)
{
std::set setCan;
Cat(setCan, a, b);
for (const auto& it : setCan)
{
Cat(m_setCan, it, c);
}
}
void Cat(std::set& setCan,string a, string b)
{
int i = min(a.length(), b.length());
for (; i >= 1 ; i–)
{
const auto tmp1 = a.substr(a.length() - i);
const auto tmp2 = b.substr(0, i);
if (tmp1 == tmp2)
{
setCan.emplace(a + b.substr(i));
}
}
setCan.emplace(a + b);
if (-1 != a.find(b))
{
setCan.emplace(a);
}
}
std::set m_setCan;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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


相关文章
|
3天前
|
搜索推荐 编译器 C语言
【C++核心】特殊的元素集合-数组与字符串详解
这篇文章详细讲解了C++中数组和字符串的基本概念、操作和应用,包括一维数组、二维数组的定义和使用,以及C风格字符串和C++字符串类的对比。
21 4
|
1月前
|
算法
【算法】滑动窗口——找到字符串中所有字母异位词
【算法】滑动窗口——找到字符串中所有字母异位词
|
1月前
|
算法 Java
掌握算法学习之字符串经典用法
文章总结了字符串在算法领域的经典用法,特别是通过双指针法来实现字符串的反转操作,并提供了LeetCode上相关题目的Java代码实现,强调了掌握这些技巧对于提升算法思维的重要性。
|
1月前
|
算法 C++ 容器
C++标准库中copy算法的使用
C++标准库中copy算法的使用
17 1
|
24天前
|
存储 C++
C++(五)String 字符串类
本文档详细介绍了C++中的`string`类,包括定义、初始化、字符串比较及数值与字符串之间的转换方法。`string`类简化了字符串处理,提供了丰富的功能如字符串查找、比较、拼接和替换等。文档通过示例代码展示了如何使用这些功能,并介绍了如何将数值转换为字符串以及反之亦然的方法。此外,还展示了如何使用`string`数组存储和遍历多个字符串。
|
1月前
|
算法 搜索推荐 C++
c++常见算法
C++中几种常见算法的示例代码,包括查找数组中的最大值、数组倒置以及冒泡排序算法。
17 0
|
2月前
|
自然语言处理 算法 搜索推荐
字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析
在自然语言处理领域,人们经常需要比较字符串,这些字符串可能是单词、句子、段落甚至是整个文档。如何快速判断两个单词或句子是否相似,或者相似度是好还是差。这类似于我们使用手机打错一个词,但手机会建议正确的词来修正它,那么这种如何判断字符串相似度呢?本文将详细介绍这个问题。
240 1
|
1月前
|
算法 C++ 容器
【C++算法】双指针
【C++算法】双指针
|
1月前
|
算法 C++
惊爆!KPM算法背后的秘密武器:一行代码揭秘字符串最小周期的终极奥义,让你秒变编程界周期大师!
【8月更文挑战第4天】字符串最小周期问题旨在找出字符串中最短重复子串的长度。KPM(实为KMP,Knuth-Morris-Pratt)算法,虽主要用于字符串匹配,但其生成的前缀函数(next数组)也可用于求解最小周期。核心思想是构建LPS数组,记录模式串中每个位置的最长相等前后缀长度。对于长度为n的字符串S,其最小周期T可通过公式ans = n - LPS[n-1]求得。通过分析周期字符串的特性,可证明该方法的有效性。提供的C++示例代码展示了如何计算给定字符串的最小周期,体现了KPM算法在解决此类问题上的高效性。
52 0
|
2月前
|
算法 C++
2730. 找到最长的半重复子字符串(c++,滑动窗口)
2730. 找到最长的半重复子字符串(c++,滑动窗口)