子串的匹配算法通常称为串的模式匹配或串匹配。通常使用的匹配算法有BF算法和KMP算法
主串S和模式串T,若匹配成功返回主串中首次出现的位置,否则返回-1;
BF算法:(暴力匹配算法)//只要失败就重新比较
时间复杂度:最优时间复杂度O(m+n);最坏时间复杂度O(mn);//n和m分别为主串和模式串的长度
算法步骤:(一般情况n>>m)
1)声明两个指针i与j分别指向主串S和模式串T当前待比较的字符位置。
2)如果i与j均未到达主串S和模式串T的尾部循环进行一下步骤:
如果S[i]==T[j]:则i++和j++; //两指针同时后移
反之S[i]!=T[j]:j=1,i=i-j+2;//j指针置1,i指针从上一次的下一个位置进行匹配
(推导:假设在j处失配,则在之前j-1必定匹配成功,那么在主串S中当前指针为i回退j-1位即到达上一次匹配位置进行+1操作便为下一次主串的匹配位置) 公式i=i-(j-1)+1 --> i=i-j+2;
循序结束时:如果j>T.length(模式串T的长度),说明匹配成功,返回i-T.length;
反之匹配失败,返回-1;
BF代码(c++):
int BF(string S,string T,int pos){//BF算法
int i=pos;//起始遍历位置
int j=1;//起始的模式串位置
while(i<=S.length()&&j<=T.length()){//均未到达两串的末尾
if(S.at(i-1)==T.at(j-1)){
i++;
j++;//相同比较下一个
}
else{
i=i-j+2;//回退到上一次的位置的下一个(i-j+2)
j=1;//重新匹配
}
}
if(j>T.length()){
return i-T.length();//返回的第一个字符的位置即为i的当前值减去模式串长度
}
return 0;//匹配失败返回0
}
注:虽然BF算法的时间复杂度为O(mn),但在一般情况下,执行时间近似于O(m+n)
KMP算法:KMP算法为BF算法的改进算法,是由Knuth、Morris、Pratt同时设计实现的,因此叫KMP算法
由于BF算法每次失配主串S都回退到上一次的下一个位置,模式串也回溯到起始位置,时间复杂度较高(举个例子)
1 2 3 4 5 6 7 8 9 10 11 14 15
S:a b a b c a b c a c b a b //主串S
T:a b c a c //模式串T
第一次匹配失败时:当匹配到第3位时(c!=a)BF算法中主