字符串匹配算法第一篇——暴力匹配
字符串匹配是一项重要的内容,本处我们讨论的字符串匹配是完全匹配,也就是找出子字符串在父字符串中的匹配位置。
例如:父字符串:EDGRNGIGEDEDGEDGLGDEDG,子字符串:EDG;则需要知道“EDG”在父字符串中的位置。先上代码:
1 //使用暴力穷举法完成字符串匹配算法 2 # include "iostream" 3 #include"string" 4 #include"vector" 5 using namespace std; 6 vector<int>& BFmatch(string & , string & , vector<int>&); 7 void ShowPos(vector<int>& ); 8 int main() 9 { 10 string ModelStr, SonStr; 11 vector<int> pos; 12 cout << "请输入待匹配字符串:"; 13 cin >> ModelStr ; 14 cout << endl; 15 cout << "请输入子字符串:"; 16 cin >> SonStr; 17 cout << endl; 18 BFmatch(ModelStr, SonStr, pos); 19 ShowPos(pos); 20 system("pause"); 21 } 22 vector<int>& BFmatch(string & ModelStr, string & SonStr,vector<int>& pos) 23 { 24 for (int i = 0; i < ModelStr.size(); i++) 25 { 26 int k = 0; 27 for (int j = i; k < SonStr.size(); j++, k++) 28 { 29 if (SonStr[k] == ModelStr[j]) 30 continue; 31 else 32 break; 33 } 34 if (k == SonStr.size()) 35 pos.push_back(i); 36 } 37 return pos; 38 } 39 void ShowPos(vector<int>& pos) 40 { 41 if (pos.size() != 0) 42 { 43 cout << "the first position of MatchingStr:"; 44 for (int i = 0; i < pos.size(); i++) 45 { 46 cout << pos[i] << "\t"; 47 } 48 cout << endl; 49 } 50 else 51 cout << "no such string!" << endl; 52 }
需要说明的是:函数BFmatch的返回类型为vector<int>&,返回类型为引用类型。需要理解的是为什么这里返回来的是vector<int>& 类型?
我们需要明确的一点是:函数的返回类型是:函数返回值的类型!!!这句话很重要。返回值是pos变量,pos变量类型是传递在形参里面;而在形参中pos的类型是vector<int>&。这里为什么是vector<int>&类型,可能我们会想到说是我们的初衷是返回一个存储匹配位置的向量,空间比较大,采用这种方式可以节省空间,采用值传递的方式不节省开销。还有没有别的解释呢?
的确,我们假设不考虑这个空间节省的问题。甚至不传递pos变量,最后让这个函数返回一个局部变量,最终将这个局部变量赋值给main函数中的pos,这当然也是可以的,但是这其中不仅仅带来了空间开销,更重要的是程序设计理念。
这个设计里面是:一个函数的名字和形参,从功能和接口的角度看,我们希望包含:程序名、输入接口,输出接口。也就是我们希望每个函数的返回值(也就是我们的输出)直接反映在函数体抬头。(在opencv的库中大量使用了这种手法)。也就是:函数名,输入端子,输出端子 来描述函数是一种更为科学的表述方式。而我们要想将输出端子作为一种公共接口,自然不能使用局部变量的方式,局部变量只在本作用域起作用。因此我们需要使用一种公共接口的方式来定义输出端子,而采用引用传递就是一种公共接口的实现方式(当然还有其他方式)。
因此,在后续的程序设计中,考虑函数名,输入接口,输出接口的方式来看待程序设计,是一种更为高级的抽象方式。