朴素的模式匹配(暴力法)算法
串的模式匹配KMP算法:https://blog.csdn.net/kjcxmx/article/details/82587924
什么是模式匹配、常见模式匹配算法及C/C++/Java代码 详见:https://blog.csdn.net/kjcxmx/article/details/82348917
算法思想:
从目标串的的第一个字符起与模式串的第一个字符比较,若相等,则继续对字符进行后续的比较,否则目标串从第二个字符起与模式串的第一个字符重新比较,直至模式串中的每个字符依次和目标串中的一个连续的字符序列相等为止,此时称为匹配成功,否则匹配失败。
某度的解释:
若模式子串的长度是m,目标穿的长度是n,这时最坏的情况是每遍比较都在最后出现不等,即没变最多比较m次,最多比较n-m+1遍,总的比较次数最多为m(n-m+1),因此朴素的模式匹配算法的时间复杂度为O(mn)。朴素的模式匹配算法中存在回溯,这影响到匹配算法的效率,因而朴素的模式匹配算法在实际应用中很少采用。在实际应用主要采用无回溯的匹配算法,KMP算法和BM算法均为无回溯的匹配算法。
如下例子:主串T为“BABABCAB”,模式串S为“ABCA”。
A、见下图BF.1开始第一步的匹配,i = 0,j = 0时(从0开始的),主串的值不等于模式串的值,则进行下一步,也就是 j++而也相应i++。
B、见下图BF.2开始第二步的匹配,T[1] = S[0],所以第一个字符是匹配的,那么将进行第二个字符的验证,也就是 j++而也相应i++。
C、见下图BF.3开始第二步的匹配,T[2] = S[1],所以S中第二个字符也是匹配的,那么将进行S中第三个字符的验证,也就是 j++而也相应i++。
D、见下图BF.4开始第三步的匹配,T[3] != S[3],所以S中第三个字符是不匹配的,那么将进行回溯,就是一下回到开始的位置,之前匹配的S[0]和S[1]的结果无效了。所以对于i来说赋值为i = 2,对应的j 将返回为j = 0,重复第A、B、C、以上步骤,这里省略。
E、见下图BF.5开始匹配,T[6] = S[3],所以S中第四个字符也是匹配的,因为模式串S结束,所以将匹配成功。
E、如果模式串为S="AAAA",则不会匹配成功,那么将会返回-1,匹配失败,对于时间复杂度来讲就是最坏情况。
C代码:
#include <stdio.h>
#include <string.h>
int index (char S[],char T[]){
int lenS,lenT;
int i=1,j=1; //注意,这里是从开始的,图解为从0开始
lenS=strlen(S)-1;//主串S实际长度
lenT=strlen(T)-1;//子串T实际长度
while ( i<=lenS && j<=lenT ){
if ( S[i] == T [j] ){//若两字符相等,对应+1
++i;
++j;
}else{
i=i-(j-1)+1; //主串回到上次匹配的下一位
j=1; //子串从头开始匹配,开始设置为1为开始
}
}
if ( j>lenT ){
return i-lenT;
}else{
return -1;
}
}
int main(){
char T[]=" abcdabcdeabcdef";
char S[]=" abcdef";
int pos; //位置
pos = index(T,S);
printf("%d",pos);
return 0;
}
C++代码:
#include <iostream>
#include <string>
using namespace std;
using std::string;
int BruteForce(string Text, string Pattern){
int lenT = Text.length();
int lenP = Pattern.length();
int s,i;
for (s = 0; s <= lenT-lenP; s++){
i = 0;
bool bEqual = true;
while (bEqual && (i < lenP)){
if (Text[s+i] == Pattern[i]){
i++;
}else{
bEqual = false;
}
}
if (bEqual){
return s;
}
}
return -1;
}
int main (){
string T = "abcdabcdeabcdef";
string S = "abcde";
int result = BruteForce(T,S);
cout << result;
return 0;
}
Java 代码:
/**
* 暴力法求解(朴素模式匹配)
* @param ts 主串(目标串)
* @param ps 模式串(匹配串)
* @return
*/
public static int bruteForce(String ts, String ps) {
char[] t = ts.toCharArray();
char[] p = ps.toCharArray();
int i = 0; // 主串的位置
int j = 0; // 模式串的位置
while (i < t.length && j < p.length) {
if (t[i] == p[j]) { // 当两个字符相同,就比较两者的下一个
i++;
j++;
} else {
i = i - j + 1; // 若不匹配,则i后退回溯,就是这一步增加了复杂度
j = 0; // j赋值为0
}
}
if (j == p.length) {
return i - j;
} else {
return -1; //匹配失败,返回-1
}
}
其实这个算法是比件容易理解的,只要理解了算法的思想就好,但这种算法对于时间复杂度要求较高,一般不推荐,尤其是数据量较大时,影响算法效率,增大不必要的开销。