在线性时间内在给定位置将字符插入字符串

时间:2017-11-01 12:51:24

标签: c++ string algorithm boost data-structures

我有一个std::string和一系列int s。我想在 int指示的位置之前添加字符。此操作应该就地执行。举个例子来考虑:

string: "abcde"
positions: 1, 3
character to be inserted: ' '
=> string after modification: "a bc de"

Algorithmwise,在O(n)时间内实现它没有问题,但我怀疑这已经在例如某处实现了。促进。但是,我找不到那里的实现。是否有提供此功能的C ++库?

2 个答案:

答案 0 :(得分:1)

更新更新到包含就地操作要求的问题:

Live On Coliru

#include <algorithm>
#include <vector>
#include <cassert>
#include <array>

template <typename What>
void multi_insert(std::string& text, std::vector<size_t> positions, What const& insertion) {
    using std::begin;
    using std::end;
    assert(std::is_sorted(positions.begin(), positions.end()));

    auto source_n  = text.length();
    auto extension = insertion.size() * positions.size();

    text.resize(text.length() + extension);

    using Rit     = std::string::reverse_iterator;
    Rit dest_it   = text.rbegin(),
        source_it = dest_it + extension;

    auto posit = positions.rbegin();

    while (dest_it != source_it) {
        assert(*posit <= source_n);

        for (;source_n && *posit != source_n; --source_n)
            *dest_it++ = *source_it++;

        dest_it = std::copy(std::make_reverse_iterator(insertion.end()), std::make_reverse_iterator(insertion.begin()), dest_it);
        ++posit;
    }
}

void multi_insert(std::string& text, std::vector<size_t> positions, char insertion = ' ') {
    multi_insert(text, std::move(positions), std::array<char, 1> {{insertion}});
}

#include <iostream>

static size_t constexpr NONE = -1;

template <typename What>
void do_tests(What const& insertion) {
    std::vector<size_t> p;

    for (size_t a : { NONE, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul })
    for (size_t b : { NONE, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul })
    {
        if (b<a) 
            continue;

        p.assign({a,b});
        p.erase(std::remove_if(p.begin(), p.end(), [](auto n) { return n == NONE; }), p.end());

        std::string text = "abcde";
        multi_insert(text, p, insertion);

        auto opt = [](size_t n) -> char { return n==NONE?'.':('0'+n); };
        std::cout << opt(a) << " " << opt(b) << " Result: '" << text << "'\n";
    }
}

int main() {
    do_tests('!');
    do_tests(std::string("***"));
}

打印

. . Result: 'abcde'
0 . Result: '!abcde'
0 0 Result: '!!abcde'
0 1 Result: '!a!bcde'
0 2 Result: '!ab!cde'
0 3 Result: '!abc!de'
0 4 Result: '!abcd!e'
0 5 Result: '!abcde!'
1 . Result: 'a!bcde'
1 1 Result: 'a!!bcde'
1 2 Result: 'a!b!cde'
1 3 Result: 'a!bc!de'
1 4 Result: 'a!bcd!e'
1 5 Result: 'a!bcde!'
2 . Result: 'ab!cde'
2 2 Result: 'ab!!cde'
2 3 Result: 'ab!c!de'
2 4 Result: 'ab!cd!e'
2 5 Result: 'ab!cde!'
3 . Result: 'abc!de'
3 3 Result: 'abc!!de'
3 4 Result: 'abc!d!e'
3 5 Result: 'abc!de!'
4 . Result: 'abcd!e'
4 4 Result: 'abcd!!e'
4 5 Result: 'abcd!e!'
5 . Result: 'abcde!'
5 5 Result: 'abcde!!'
. . Result: 'abcde'
0 . Result: '***abcde'
0 0 Result: '******abcde'
0 1 Result: '***a***bcde'
0 2 Result: '***ab***cde'
0 3 Result: '***abc***de'
0 4 Result: '***abcd***e'
0 5 Result: '***abcde***'
1 . Result: 'a***bcde'
1 1 Result: 'a******bcde'
1 2 Result: 'a***b***cde'
1 3 Result: 'a***bc***de'
1 4 Result: 'a***bcd***e'
1 5 Result: 'a***bcde***'
2 . Result: 'ab***cde'
2 2 Result: 'ab******cde'
2 3 Result: 'ab***c***de'
2 4 Result: 'ab***cd***e'
2 5 Result: 'ab***cde***'
3 . Result: 'abc***de'
3 3 Result: 'abc******de'
3 4 Result: 'abc***d***e'
3 5 Result: 'abc***de***'
4 . Result: 'abcd***e'
4 4 Result: 'abcd******e'
4 5 Result: 'abcd***e***'
5 . Result: 'abcde***'
5 5 Result: 'abcde******'

答案 1 :(得分:0)

我无法想到一个完全符合标准的标准实现,但您可以使用以下方法实现此目的:

int main() {
  std::string input { "abcde" };
  std::set<size_t> positions { 1, 3 };
  char separator = ' ';

  std::string output;
  output.reserve(input.size() + positions.size()); // Make sure (at most) a single allocation is performed

  unsigned index = 0;
  auto pos = positions.begin();
  for (auto & i : input)
  {
    if (pos != positions.end() && *pos == index)
    {
      output += separator;
      ++pos;
    }

    output += i;
    ++index;
  }

  std::cout << output << std::endl;
}

假设n是输入字符串的长度,m是位置矢量的长度,则执行:

O(n + m) [Allocation] + O(n + m) [Copy] = O(n + m) [Total]