Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我能做些什么来加速这段代码(字符串相似性)? 这是一个C++代码,使用标准库来查找字符串S与每个后缀的字符串相似性。_C++_String - Fatal编程技术网

我能做些什么来加速这段代码(字符串相似性)? 这是一个C++代码,使用标准库来查找字符串S与每个后缀的字符串相似性。

我能做些什么来加速这段代码(字符串相似性)? 这是一个C++代码,使用标准库来查找字符串S与每个后缀的字符串相似性。,c++,string,C++,String,尽管它给出了正确的输出,但对于大型字符串,这样做需要花费大量时间。代码如下: #include <iostream> #include <string> using namespace std; int sim(string a, string b){ int count=0; int sa=a.size(); int sb=b.size(); int iter; if(sa>sb) iter=sb; else it

尽管它给出了正确的输出,但对于大型字符串,这样做需要花费大量时间。代码如下:

#include <iostream>
#include <string>
using namespace std;

int sim(string a, string b){
    int count=0;
    int sa=a.size();
    int sb=b.size();
    int iter;
    if(sa>sb) iter=sb;
    else iter=sa;
    for(int i=0; i<iter; i++){
        if (a[i]!=b[i]) break;
        else count++;
    }
    return count;
}

int strsim(string a){
    int sum=0;
    int s=a.size();
    for(int i=0; i<s; i++){
        sum=sum+sim(a,a.substr(i));
    }
    return sum;
}

int main(){
    int n;
    cin >> n;
    string a[n];
    for(int i=0; i<n; i++){
        cin >> a[i];
    }
    for(int i=0; i<n; i++){
        cout << strsim(a[i]) << '\n';
    }
}
输出:

11

i、 e,
6+0+3+0+1+1=11

当前代码计算长度为L的单个字符串,单位为
O(L^3)
(substr需要线性运行时间)。更不用说,由于字符串传递效率低下,导致上述复杂性的高固定成本

您的算法可以简化为查找字符串及其所有后缀的最长公共前缀。这可以很容易地使用。这个概念无法解释为一个答案,所以我强烈推荐你

次优且易于编码的后缀数组解决方案将有
O(Llg^2(L))
(L=字符串长度)构造时间和
O(1)
时间来使用。请注意,整个字符串本身就是它自己的后缀。在本例中,需要对每个字符串进行L查询。因此,一个字符串的总复杂度将是
O(Llg^2(L))+O(L)


如果您想进一步改进,您可以通过使用基数排序将构造时间减少到
O(Llg(L))
,或者减少到
O(L)
()

这里的最大成本是按值传递字符串-这意味着每次调用“sim”都会创建两个全新的字符串并将数据复制到它们。您应该消除这一点,并将其替换为按引用传递

#include <iostream>
#include <string>
#include <vector>
using namespace std;

size_t compareSubstring(const std::string& str, size_t offset)
{
    size_t count = 0;
    std::string::const_iterator lhsIt = str.begin();
    std::string::const_iterator rhsIt = str.begin() + offset;
    for ( ; rhsIt != str.end() ; ++lhsIt, ++rhsIt ) {
        if (*lhsIt != *rhsIt)
            break;
        ++count;
    }
    return count;
}

int compareString(const string& str)
{
    size_t count = 0;
    const size_t length = str.size();
    for(size_t i = 0; i < length; ++i) {
        count += compareSubstring(str, i);
    }
    return count;
}

int main()
{
    size_t numStrings = 0;
    std::cin >> numStrings;

    std::vector<std::string> strings;
    strings.resize(numStrings);

    for(size_t i = 0; i < numStrings; ++i) {
        std::cin >> strings[i];
    }

    for(size_t i = 0; i < numStrings; ++i) {
        std::cout << compareString(strings[i]) << std::endl;
    }
}
#包括
#包括
#包括
使用名称空间std;
大小比较子字符串(常量std::string和str,大小偏移)
{
大小\u t计数=0;
std::string::const_迭代器lhsIt=str.begin();
std::string::const_迭代器rhsIt=str.begin()+偏移量;
对于(;rhsIt!=str.end();++lhsIt,++rhsIt){
如果(*lhsIt!=*rhsIt)
打破
++计数;
}
返回计数;
}
整数比较字符串(常量字符串和字符串)
{
大小\u t计数=0;
const size_t length=str.size();
对于(尺寸i=0;i>数值字符串;
std::向量字符串;
strings.resize(numStrings);
对于(大小i=0;i>字符串[i];
}
对于(大小i=0;i
因此,仅当大写字母“a”和“a.substring”中的两个字符串的第一个字符相等时,才调用sim函数

     int strsim(string a){
     int sum=0;
     int s=a.size();
     for(int i=0; i<s; i++){

     if(a[i] == a[0])  //add this extra line
     sum=sum+sim(a,a.substr(i));

     }
    return sum;
   }
int strsim(字符串a){
整数和=0;
int s=a.size();

对于(int i=0;i,这里的效率尽可能高(无需进入FFT领域):

求和i=0^j求和j=0^s f\u i,j

int strsim(const string &a){
    int s=a.size();
    int sum=0;
    for(int i=0; i<s; i++){
        for (int j=i;j<s;++j){
            if (a[j-i]!=a[i]) break;
            sum ++;
        }
    }
    return sum;
}
int strsim(常量字符串&a){
int s=a.size();
整数和=0;

对于(int i=0;i首先,您应该检查是否有更好的算法。然后,根据您准备投入的资金和松散的可移植性,如果您的编译器没有做到这一点,您可能需要手动对代码进行向量化。使用gcc intrinsic(参见示例)我已经能够在类似的代码上获得x6加速。

您可以始终将函数中的字符串参数作为常量引用而不是副本传递。还可以通过编译器启用更多优化。
a.substr(I)
返回一个全新的字符串,这会导致动态分配。请将函数更改为使用迭代器(与大多数C++算法一样),这样你就可以把不同的迭代器传递到字符串中,或者你可以切换到使用<代码> char */COD>,在你的代码> StruS/<代码>函数中比较<代码> A<代码> > <代码>和[i]
。你的例子是错误的-结果应该是12。第二个0应该是1。这段代码将OP的代码从
O(L^3)
减少到
O(L^2)
,常数因子减少得很高。但是,由于L可以达到100000,
O(L^2)
仍然是不切实际的。
a.substr(i)[0]
是一个可怕的建议。Do
a[i]
取而代之。@cluracan,你说得对,我考虑过了,但我没有时间编辑它,无论如何,谢谢。:)
int strsim(const string &a){
    int s=a.size();
    int sum=0;
    for(int i=0; i<s; i++){
        for (int j=i;j<s;++j){
            if (a[j-i]!=a[i]) break;
            sum ++;
        }
    }
    return sum;
}