【问题标题】:Is there optimal way to find substring with reapiting pattern in a string in C++?是否有在 C++ 中的字符串中查找具有重复模式的子字符串的最佳方法?
【发布时间】:2020-05-12 14:40:01
【问题描述】:

我正在努力解决我需要为我的在线课程解决的问题。通常我的老师会很乐意提供帮助,但现在无法联系到他。问题如下:

如果有两个相同的子字符串彼此相邻,我们可以通过将其写为 (substring) 来压缩它。因此,我们可以将 zz 写为 (z) 并将 zzzz 写为 ((z)) 或 zzzzzzzzzzbb 写为 (((z)))(z)(b)。给定一个压缩文本检查压缩是否正确,如果可能的话 - 解压缩并检查压缩是否以最佳方式完成,可能通过再次优化压缩。

我已经编写了一个函数来检查压缩是否正确,解压缩函数和最佳压缩,但仅适用于只有一种模式的字符串(如 gorgorgorgorgorgor 或 zzzzzz)以及何时知道该模式。

std::string ifreapeats(std::string tes, std::string dotes){

int iloraz = dotes.length() / tes.length();
int pot2 = highestpow2(iloraz);
int roznica = iloraz - pot2;

std::string finale;

finale = "";

int logar = int(log(iloraz) / log(2));

    for(int i = 0; i < logar; ++i)
    {
        finale += '(';
    }

    finale += tes;

    for (int i = 0; i < logar; ++i)
    {
        finale += ')';
    }

    if (roznica == 1)
        return finale + tes;

    if (roznica == 0)
        return finale;

    std::string dotes2 = "";

    for (int i = 0; i < roznica; ++i)
    {
        dotes2 += tes;
    }

    finale += ifreapeats(tes, dotes2);

    return finale;}

highestpow2 返回小于或等于给定数字的 2 的最大幂。现在我不知道如何将它应用于更复杂的字符串,其中有多个模式并且有没有模式的序列。例如 aabbbaabbbxyzyz。它应该返回 ((a)(b)b)x(yz)。我想找到最长的模式子串可能会起作用,但我不知道如何应用它。这也比我们之前在 IT 课上所做的要困难得多。如果这不是问题,我希望得到一些解释,以便我可以帮助班上的其他学生(每个人都希望我能解决问题并帮助他们)。

抱歉,我可能犯了一些语法错误。我也可能在波兰语中留下了一些变量名称,对此我也深表歉意。

【问题讨论】:

  • (z) 是如何压缩zz 的?前者占用 3 个字符,后者占用 2 个字符,因此 zz(z) 更压缩。另外,为什么zzzzzzzzzz 不等于((((z))))
  • 什么是“最佳”压缩?我想那个会产生最短的压缩字符串,但是如果分配要求“最佳压缩”,我希望它带有一个应该是什么的定义
  • 寻找重复的子串构成了霍夫曼编码的核心,并且有大量的文献解释了基本方法,以及这样做的基本算法。您要么不知道算法、基本方法,要么您知道但对在 C++ 中实现它有疑问。如果您不了解基本算法,可以阅读大量可用的文献(包括维基百科)。在这里逐字复制/粘贴它没有任何用处。如果您有特定的 C++ 应用程序问题,关于此,您需要澄清您的特定问题是什么。
  • @Stanis 你的老师没有逃到树林里烧掉他们的指纹。我保证他们有工作电子邮件。可能在您的学校网站上列出。我觉得你可以在这里寻求帮助,但我也认为你应该和你的老师联系。如果他们没有列出电子邮件,您可以查看他们的老板是否有电子邮件。如果他们的老板没有,你试试校长。或一般的“contact@school.gov.pl”电子邮件地址。
  • 他们现在有什么样的老师,像那样完全遥不可及?多么可悲的状况。在我上高中的时候,就像现在一样,我在课堂上和我的导师面对面地交谈和讨论事情,每天。这是我做的好事。毕竟,那时还没有 stackoverflow.com。所以,我所需要帮助我弄清楚一切的就是我的智慧。还有我的老师们。

标签: c++ substring


【解决方案1】:

我还没有证明这种方法会产生最佳的“压缩”,但我的直觉是从最长的重复开始,然后向内走。如果这不是最佳的,那么在我看来,这项任务远高于高中水平的任务。

思路如下:寻找最长的重复。一旦你找到了它,那么字符串可以分为 ABBC 部分,其中 B 是重复,A 和 C 是重复前后的子串。结果由A的压缩,'(',B的压缩,')'和C的压缩连接给出。如果没有发现重复,则压缩是输入字符串。

您可以使用以下算法,用伪代码编写:

// size(S) is the size of the string
// substr(S, Pos, L) is substring of S with length L starting from Pos
// substr(S, Pos) is substring of S starting from Pos until the end of S
// S is the input string
compress(S)
    if size(S) < 2
        return S     // strings shorter than 2 cannot have repetition
    L = size(S) / 2  // L is initially longest possible repetition
    while L > 0
        for I = 0 ... size(S) - 2*L
            Left  = substr(S, I    , L)
            Right = substr(S, I + L, L)
            if Left == Right    // repetition found
                Beforeleft = substr(S, 0      , I)
                AfterRight = substr(S, I + 2*L)
                return
                    compress(Beforeleft) +
                    '(' +
                    compress(Left) +
                    ')' +
                    compress(AfterRight)
        L--     // no repetition of this length found; search for shorter
    return S    // no repetition of any length was found

【讨论】:

  • 非常感谢!我将尝试将其应用于 cpp 并提供反馈是否我设法这样做!
  • 有效,又快又准!非常感谢你!!!而且(最重要的是)我完全理解它,我可以向我的同学解释!此外 - 它比我编写的总共有 150 多行的代码更简单、更短。
猜你喜欢
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
相关资源
最近更新 更多