簡體   English   中英

是否有 std::string 子字符串的替代方法?

[英]Is there an alternative to the std::string substring?

給定一個字符串s = "RADILAMIA"我想取長度為 4(或其他)的所有子字符串。

如果len == 4則子串是:“RADI”、“ADIL”、“DILA”、“ILAM”、“LAMI”、“AMIA”。 使用std::string substr方法似乎很容易做到這一點:

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;
}

substr的時間復雜度未指定,但通常與子字符串的長度成線性關系。

我可以在沒有std::string substr情況下做到這一點。 任何子串和前一個子串只有一個字母不同。 有沒有更好的方法來降低時間復雜度?

可以有數百萬種不同的方法。 這是我的算法。

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 會有所作為,因為不會有復制成本。 您還可以添加儲備以獲得更高的性能。

無論您做什么,您仍然需要 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);
}

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比函數的返回值更長。

也許你可以使用一個字符數組來代替。 例如,你有話要說:

char s[] = "RADILAMIA";

要處理所有必要的子字符串,您可以使用這種方法:

int substLength = 4;
int length = strlen(s);
char buffer[256];
for (int i = 0; i < length - substLength + 1; i++) {
    strncpy(buffer, s + i, substLength);
    buffer[substLength] = '\0';
    cout << buffer << endl;
}

使用 char 數組,您可以通過將必要的索引添加到數組的開頭來輕松訪問任何子字符串的開頭。

重新審視文檔是值得的

// 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()) - 只能希望比例因子更小。

C 並不總是比 C++ 快,但 @Fomalhaut 用 C 發布高性能核心解決方案是正確的。這是我的(C 程序)完整版本,基於他的算法。 也不使用 strncpy 。

這是在神弩上

#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 

享受。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM