找到字符串子串的出现?为什么我的节目没有打印任何比赛?

时间:2017-04-20 20:00:25

标签: string algorithm

最近我得到了一个用于查找另一个字符串中字符串出现次数的赋值,类似于ctrl + f的工作方式。下面是我的实现,但我正在检测代码中的错误。

#include<iostream>

using namespace std;

int findsubstr(string s, string substr);

int main(){
    string a = "abcxyzcxy";
    string b = "cxy";
    cout << "number of matching found " << findsubstr(a, b) << endl;
    return 0;
}
int findsubstr(string mainstring, string substr){
    int i;
    int count = 0;
    if(substr.length() > mainstring.length()){
        cout << "invalid string for matching!" << endl;
        return 0;
    }
    for( i=0; i<mainstring.length(); i++){
        int j;
        for (j=0; j<substr.length(); j++){
            if(mainstring[i+j] != substr[j]){
                break;
            }
        }
        if(j==substr.length()-1){
            cout << "pattern found at " << i << endl;
            count++;
        }
    }
    return count;
}

我在网上找到的代码几乎完全相同,但我的程序似乎从来没有找到匹配,即使有一个。以上示例有两个。我的逻辑是将i作为mainstring的索引,将j作为substring的索引。然后,如果子串中的所有字符都匹配从mainstring开始的字符,则在该索引处找到pattern。

2 个答案:

答案 0 :(得分:3)

for(i = 0; i <= mainstring.length()-substr.length(); i++){
    int j;
    for (j = 0; j < substr.length(); j++){
        if(mainstring[i+j] != substr[j]){
            break;
        }
    }
    if(j == substr.length()){
        cout << "pattern found at " << i << endl;
        count++;
    }
}

你的逻辑是正确的,但问题是j增加到最后一次迭代的模式长度。 您的程序运行时间最差为O(mn),其中m是模式的长度,n是您尝试查找模式的字符串的长度。

在现实生活中,ctrl + f使用更优化的算法,大大减少文本庞大时的运行时间。这里wiki有很多这样的算法。

例如,

KMP假设您有文字s = ababac和模式m = abac,您会发现s[3]bm[3]之间存在不匹配, c。不过,我们知道ab中的abababac中的前缀,因此我们可以跳过检查模式中的ab并查找ac,但是,这需要一个预处理的查找表。

答案 1 :(得分:1)

这只是因为你将j与substr.length() - 1进行比较。

当匹配时j已经变为substr.length()。因此,您应该使用substr.length()进行比较。以下是完整的计划。

#include<iostream>

using namespace std;

int findsubstr(string s, string substr);

int main(){
    string a = "abcxyzcxy";
    string b = "cxy";
    cout << "Number of matching found " << findsubstr(a, b) << endl;
    return 0;
}
int findsubstr(string mainstring, string substr){
    int i;
    int count = 0;
    if(substr.length() > mainstring.length()){
        cout << "invalid string for matching!" << endl;
        return 0;
    }
    for( i=0; i<mainstring.length(); i++)
    {
    int j;
        for (j=0; j<substr.length(); j++)
    {
            if(mainstring[i+j] != substr[j])
        {
                break;
            }
        }
        if(j==substr.length()){
            cout << "pattern found at " << i << endl;
            count++;
        }
    }
    return count;
}