最近我得到了一个用于查找另一个字符串中字符串出现次数的赋值,类似于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。
答案 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]
,b
和m[3]
之间存在不匹配, c
。不过,我们知道ab
中的abab
是abac
中的前缀,因此我们可以跳过检查模式中的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;
}