[小明学算法]7.字符串匹配算法---BM
1.简介
BM算法是比较优秀的字符串匹配算法.
2.主要思想介绍
BM算法主要有三个要点
①.从pattern的后面往前比较
②.对匹配过的数据应用KMP
③.将pattern向右滑,找到与string当前字符匹配的a相同的字符位置(若不存在,直接滑过sizeof(length))
(第三步目前只实现了滑过在右侧以匹配过字符不存在的情况)
3.代码
1 #include <iostream> 2 using namespace std; 3 bool isSub(char* A, char* B, int lengthA, int lengthB); 4 void Print(int* table, int length); 5 //记录字符在pattern中的最后位置 6 int* PreBMLocation(char* pattern, int length) 7 { 8 //字符的最大值为256 9 int* location = new int[256]; 10 for (int i = 0; i < 256; i++) 11 location[i] = length; 12 for (int i = 0; i < length; i++) 13 location[pattern[i]] = length-i-1; 14 15 return location; 16 } 17 18 //和KMP一样的从后往前比对思路 19 void PreBMTable(char* pattern, int *Table, int length) 20 { 21 //设定哨兵 22 Table[length] = 1; 23 //为每一个pattern[i]计算可偏移值(即之前有多少重复) 24 for (int i = length - 1; i >= 0; i--) 25 { 26 Table[i] = Table[i + 1]; 27 //计算从新加入的重复 28 for (int j = length - Table[i]; j >= i; j--) 29 { 30 31 //从i到j是否是已经匹配过的子串 32 if (isSub(pattern, pattern + i, length, j - i)) 33 { 34 //如果存在一个字串,结束 35 break; 36 } 37 else 38 { 39 //如果不存在重复部分,移动量加一 40 Table[i]++; 41 } 42 } 43 } 44 } 45 46 //B是否是A的尾子串(从末尾一位开始比较) 47 bool isSub(char* A, char* B, int lengthA, int lengthB) 48 { 49 int start = lengthA - lengthB; 50 for (int i = lengthB - 1; i >= 0; i--) 51 { 52 if (A[start + i] != B[i]) 53 return false; 54 } 55 56 return true; 57 } 58 59 void Print(int* table, int length) 60 { 61 for (int i = 0; i < length; i++) 62 { 63 cout << table[i] << " "; 64 } 65 cout << endl; 66 } 67 int Max(int a, int b) 68 { 69 return a>b ? a : b; 70 } 71 72 void BM(char* string, int m, char* pattern, int n) 73 { 74 //BM算法主要有三个要点 75 //1.从pattern的后面往前比较 76 //2.对匹配过的数据应用KMP 77 //3.将pattern向右滑,找到与string当前字符匹配的a相同的字符位置(若不存在,直接滑过sizeof(length)) 78 //(第三步目前只实现了滑过在右侧以匹配过字符不存在的情况) 79 80 //先处理pattern 81 int* table = new int[n + 1]; 82 PreBMTable(pattern, table, n); 83 int* loacation = PreBMLocation(pattern, n); 84 85 for (int i = 0; i < m; ) 86 { 87 for (int j = n - 1; j >= 0; j--) 88 { 89 char a = string[i+j]; 90 char b = pattern[j]; 91 92 if (a != b) 93 { 94 //这个是记录了string中当前比较字符在pattern中的位置,并计算移动和其匹配所做的移动数(可能为负) 95 //当不存在时,直接滑过. 96 int t = loacation[a]-(n - 1-j) ; 97 i += Max(table[j],t ); 98 //cout << t <<" t1:"<<t1 <<"a:"<<a<<endl; 99 break; 100 } 101 102 if (j == 0) 103 { 104 //第一次匹配起点在string中的位置 105 cout << i << endl; 106 return; 107 } 108 } 109 } 110 111 112 } 113 114 void main() 115 { 116 char string[] = "bcrcaaaaabbbbcd"; 117 char pattern[] = "aaaabbbbcd"; 118 int length = sizeof(pattern); 119 int* table = new int[length]; 120 121 BM(string, sizeof(string)-1, pattern, length - 1); 122 123 124 int a; 125 cin >> a; 126 }