[小明学算法]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 }
View Code
原文地址:https://www.cnblogs.com/WongSiuming/p/5130561.html