串匹配
对基于同一字符表的任何文本串T(|T| = n)和模式串P(|P| = m);
判定T中是否存在某一子串与P相同
若存在,则返回子串P在T中的起始位置。
版本A:
int match_A(string T, string P){
int i = 0, j = 0;
int n = T.length(), m = P.length();
while(i < n && j < m){
if(T[i] == P[j]){
i++; j++;
} else {
i -= j - 1;
j = 0;
}
}
return i - j;//结果 > T.length()则未找到
}
很好理解,T中字符同P轮流比较,若相等则T和P同时后移。若不等,则T后移,P呆在初始位置。上述代码不好理解的地方可能在==i -= j - 1;==这一句。其实很好理解,若T与P首次不相等,此时P在初始位置0处,减1操作相当于i+1。对于P不是呆在初始位置,同样好理解,因为初始都在0位置,因此相当于在原基础上+1。
版本B:
int match_B(string T, string P){
int n = T.length(), m = P.length();
int i = 0, j;
for(i = 0; i < n-m+1; i++){
for(j = 0; j < m; j++)
if(T[i+j] != P[j])
break;
if(j >= m) break;
}
return i;//i > p.lenght()则未找到
}
同样是轮流比较,不同的是T只需要比较前n-m+1个即可,因为若存在匹配情况,则只会出现在前n-m+1个中,在这之后P的长度已小于T的剩余长度,所以又怎么能匹配成功呢?
完整代码:
#include<iostream>
using namespace std;
int match_A(string T, string P){
int i = 0, j = 0;
int n = T.length(), m = P.length();
while(i < n && j < m){
if(T[i] == P[j]){
i++; j++;
} else {
i -= j - 1;
j = 0;
}
}
return i - j;//结果 > T.length()则未找到
}
int match_B(string T, string P){
int n = T.length(), m = P.length();
int i = 0, j;
for(i = 0; i < n-m+1; i++){
for(j = 0; j < m; j++)
if(T[i+j] != P[j])
break;
if(j >= m) break;
}
return i;//i > p.lenght()则未找到
}
int main(){
string T, P;
cin >> T >> P;
cout << match_A(T, P) << endl;
cout << match_B(T, P) << endl;
return 0;
}
时间复杂度分析:
蛮力算法至多迭代(n-m+1)* m次。因此当n >> m时,时间复杂度为O(n*m);最好情况下也要O(n+m)。
参考文献:《数据结构》邓俊辉