Почему один и тот же код может компилироваться с различными результатами?

Привет! У меня возникла проблема при решении задач на codewars. Я обнаружил, что мой код компилируется успешно в Visual Studio (MVS) с использованием стандарта C++ 17, но на сайте codewars (и в других онлайн-компиляторах) результат отличается. 

Я ожидаю, что функция is_merge должна возвращать true в обоих случаях, но в MVS я получаю этот результат, а на codewars она возвращает false. Я подозреваю, что это может быть связано с методом find, но так как я новичок в программировании, не уверен. 

Вот мой код: 

<pre><code class="cpp">#include &lt;iostream&gt;
#include &lt;unordered_map&gt;

bool is_merge(const std::string&amp; s, const std::string&amp; part1, const std::string&amp; part2)
{
    if (s.size() &lt; part1.size() + part2.size()) return false;

    std::string sCopy = s;
    std::unordered_multimap&lt;int, char&gt; part1map;
    std::unordered_multimap&lt;int, char&gt; part2map;
    int index = 0;
    int order = 0;

    for (auto&amp; letter : part1)
    {
        part1map.emplace(index, letter);
        ++index;
    }

    index = 0;

    for (auto&amp; letter : part2)
    {
        part2map.emplace(index, letter);
        ++index;
    }

    for (auto&amp; elem : part1map)
    {
        if (sCopy.find(elem.second) != std::string::npos &amp;&amp; elem.first &gt;= order) 
        {
            sCopy.erase(sCopy.find(elem.second), 1);
            order = elem.first;
        }
    }

    order = 0;

    for (auto&amp; elem : part2map)
    {
        if (sCopy.find(elem.second) != std::string::npos &amp;&amp; elem.first &gt;= order)
        {
            sCopy.erase(sCopy.find(elem.second), 1);
</code></pre>
  • 29 августа 2024 г. 19:14
Ответы на вопрос 2
Судя по вашему описанию и коду, у вас могут возникать различия в результате работы вашей функции `is_merge` из-за особенностей работы с методами `find` и `erase` в сочетании с тем, как вы обрабатываете символы из строк `part1` и `part2`. Давайте рассмотрим несколько важных моментов, которые могут привести к проблемам с вашей реализацией.

1. **Удаление символов из строки**: Когда вы удаляете символ из `sCopy` с помощью метода `erase`, индексы для оставшихся символов изменяются. Это может привести к тому, что вы не будете находить следующие вхождения символов, даже если они есть, потому что `find` будет возвращать индексы для строки, которая уже изменилась.

2. **Проблемы с порядком**: Порядок обработки символов может сыграть значительную роль. Ваш алгоритм требует, чтобы символы `part1` и `part2` встречались в правильном порядке в строке `s`. Однако, если одинаковые символы присутствуют в обеих частях, а они удаляются из `sCopy`, это может нарушить логику.

Вот один из подходов для пересмотра вашего алгоритма, чтобы учесть эти нюансы:

```cpp
#include <iostream>

bool is_merge(const std::string &s, const std::string &part1, const std::string &part2) {
    if (s.size() < part1.size() + part2.size()) return false;

    size_t i = 0, j = 0, k = 0;

    while (k < s.size()) {
        if (i < part1.size() && s[k] == part1[i]) {
            ++i;
        } else if (j < part2.size() && s[k] == part2[j]) {
            ++j;
        } else {
            return false;
        }
        ++k;
    }

    return i == part1.size() && j == part2.size();
}

int main() {
    std::string s = "codewars";
    std::string part1 = "code";
    std::string part2 = "wars";

    std::cout << std::boolalpha << is_merge(s, part1, part2) << std::endl; // должно быть true
    return 0;
}
```

Этот вариант кода использует три указателя: `i`, `j` и `k`, чтобы просматривать строки `part1`, `part2` и `s` соответственно и убедиться, что символы в `part1` и `part2` появляются в правильном порядке в `s`. Это более надежный способ определить, можно ли объединить `part1` и `part2` для получения `s`. 

Попробуйте использовать этот код и проверьте, решит ли он вашу проблему на Codewars.
Что этот код должен, по вашему делать? Я отлично вижу, как он может в этих случаях вернуть false. Если ваш цикл в вашем UNORDERED мапе сначала возьмет самый последний символ сторки part1, то он присвоит переменной order максимально возможное значение и больше ни одино условие в цикле не выполнется - ни один символ больше не удалится. 

Разница в поведении компиляторов обусловлена тем, что они по разному мешают этот самый НЕУПОРЯДОЧЕННЫЙ мап. Возможно, там разные хеш функции используются.

И, кстати, ваши multimap-ы тут вообще бесполезны. Во-первых, зачем вам MULTImap, ведь у вас все ключи - это индексы симовлов - уже разные. Во-вторых, зачем вам вообще map, если вы там по каждому индексу храние символ, что итак уже делает строка! У вас там part1map[i] == part1[i] всегда. Вместо цикла по мапу, можно пройтись циклом от 0 до длины строки.
Похожие вопросы