在c ++中有什么替代的STL子串吗?

时间:2016-12-13 07:49:12

标签: c++ string

给定一个字符串s =“RADILAMIA”。现在我想要取所有长度为4或其他的子串。如果len = 4那么子串是:“RADI”,“ADIL”,“DILA”,“ILAM “,”LAMI“,”AMIA“。使用子字符串很容易:

vector<string> allSubstr(string s,int len) {
    vector<string>ans;
    for(int i=0;i<=s.size()-len;i++) {
        ans.push_back(s.substr(i,len));
    }
    return ans;
}

substring的时间复杂度未指定,但通常在子串的长度上是线性的。我可以在没有stl子串的情况下执行此操作,因为任何子字符串和它之前的子字符串的差别只有一个字母。有没有更好的方法来减少时间复杂度?

6 个答案:

答案 0 :(得分:1)

可能有数百万种不同的方法。这是我的算法。

vector<string> allSubstr(string s,int len) {

    vector<string>ans;
    ans.reserve(s.size() - len );
    for(size_t i=0;i<=s.size()-len;i++) 
    {
        ans.emplace_back( s.begin() +i, s.begin() + i + len );
    }

    return ans;
}

经过测试。我的意思是你使用的并不重要,但上面的emplace_back可以有所作为,因为不会有复制成本。您还可以添加保留以获得更高的性能。

答案 1 :(得分:1)

无论你做什么,你仍需要O(NL)时间将所有子串写入向量。

最快的可能是:

vector<string> ans(s.size()-len);
for(int i=0;i<=s.size()-len;i++) {
    ans[i] = s.substr(i, len);
}

因为push_back很慢,一般应该尽可能避免。它被过度使用了。

PS:也许这段代码会更快:

vector<string> ans(s.size()-len);
for(int i=0;i<=s.size()-len;i++) {
    ans[i].append(s.begin()+i, s.begin()+i+len);
}

答案 2 :(得分:1)

string_view(C ++ 17)有一个恒定的时间substr

vector<string_view> allSubstr(const string_view& s, int len) {
    vector<string_view> ans;
    and.reserve(s.size() - len + 1);
    for (int i = 0 ; i <= s.size() - len; ++i) {
        ans.push_back(s.substr(i, len));
    }
    return ans;
}

只需确保s超过函数的返回值。

答案 3 :(得分:0)

重新访问docos是值得的。

// string proto(len);
vector<string> result(s.size()-len, string(len, char(32))); // preallocates the buffers

const char *str=s.c_str();
const char* end=str+s.size()-len;

for(size_t i=0; str<end; str++, i++) {
  result[i].assign(str, len); // likely to result in a simple copy in the preallocated buffer
}

复杂性是相同的O(len * s.size()) - 人们只能希望有一个较小的比例因子。

答案 4 :(得分:0)

C并不总是比C ++快,但是@Fomalhaut是用C发布高性能核心解决方案的正确方法。这是我的(C程序)完整版本,基于他的算法。也不使用strncpy。

Here it is on the godbolt

#ifdef __STDC_ALLOC_LIB__
#define __STDC_WANT_LIB_EXT2__ 1
#else
#define _POSIX_C_SOURCE 200809L
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>

//////////////////////////////////////////////////////////////
// array of buffers == a_of_b
typedef struct a_of_b  {
    const unsigned size;
    unsigned count ;
    char ** data   ;
} a_of_b ;

a_of_b a_of_b_make ( const unsigned size_ ) 
{
   return (a_of_b){ .size = size_, .count = 0, .data = calloc(1, sizeof(char * [size_] ) ) } ;
}

a_of_b * a_of_b_append ( a_of_b * self,  const unsigned len_, const char str_[len_] ) 
{
    assert( self->data ) ;
    assert( self->size > self->count ) ;
    self->data[ self->count ] = strndup( str_, len_ ) ;
    self->count += 1;
    return self ;
}

a_of_b * a_of_b_print ( a_of_b * self , const char * fmt_ ) 
{
    for (unsigned j = 0; j < self->count; ++j)
         printf( fmt_ , self->data[j]);
    return self ;
}

a_of_b * a_of_b_free ( a_of_b * self  ) 
{
    for (unsigned j = 0; j < self->count; ++j)
         free( self->data[j]) ;
    free( self->data) ;
    self->count = 0  ;         
    return self ;
}
//////////////////////////////////////////////////////////////
a_of_b breakit ( const unsigned len_, const char input_[len_], const unsigned  substLength )
{
    assert( len_ > 2 ) ;
    assert( substLength > 0 ) ;
    assert( substLength < len_ ) ;

    const unsigned count_of_buffers = len_ - substLength + 1;

    a_of_b rez_ = a_of_b_make( count_of_buffers +1 ) ;

    for (int i = 0; i < count_of_buffers ; i++) {
        a_of_b_append( &rez_, substLength, input_ + i ) ;
    }

   return rez_ ;
}
//////////////////////////////////////////////////////////////
static void driver( const char * input_, const unsigned substLength ) 
{
    printf("\n");
    a_of_b substrings = breakit( strlen(input_), input_, substLength );
    a_of_b_print( & substrings , "%s ");
    a_of_b_free( & substrings);
}
//////////////////////////////////////////////////////////////
int main () { 

    driver( "RADILAMIA", 4) ;
    driver( "RADILAMIA", 3) ;
    driver( "RADILAMIA", 2) ;
    driver( "RADILAMIA", 1) ;
    
    return EXIT_SUCCESS; 
}

程序输出为:

RADI ADIL DILA ILAM LAMI AMIA 

RAD ADI DIL ILA LAM AMI MIA 

RA AD DI IL LA AM MI IA 

R A D I L A M I A 

享受。

答案 5 :(得分:-1)

可能你可以使用一组字符代替。例如,您已经明白了:

>>> big_integer=2**100
>>> print int(math.ceil(math.log10(big_integer)))
31
>>> print big_integer
1267650600228229401496703205376

要处理所有必要的子串,您可以使用这种方法:

char s[] = "RADILAMIA";

使用char数组,您可以通过向数组的开头添加必要的索引来轻松访问任何子字符串的开头。