昨天没能把BM算法看明白,今天又把各种演示和说明文字看了一圈,大概有些明白了,但是好后缀的部分看到别人的代码又有些蒙圈,不过暂时还是记下,免得以后找都没地方找。
代码参考:典型字符串匹配算法实现
//BM算法主体
int BMMatch(char[] str, char[] subStr)
{
int[] bc = BadCharacter(subStr);
int[] gs = GoodSuffix(subStr);
int i = 0;
while(i+subStr.Length < str.Length)
{
int j = subStr.Length - 1;
while(subStr[j] == str[i+j])
{
j--;
if(j < 0)
{
break; //对比结束
}
}
if(j<0)
{
break; //对比结束
}
else
{
i += Max(gs[j], j-bc[T[i+j]]); //在坏字符的情况和好后缀的情况中选一个可移动的最长的步长
}
}
}
//记录成为坏字符的英文字符与移动步长关系的数组
int[] BadCharacter(char[] subStr)
{
int m = subStr.Length;
int[] bc = new int[256];
for(int i = 0; i<256; i++)
{
bc[i] = m;
}
for(int i = 0; i<m; i++)
{
bc[(int)subStr[i]] = m - i - 1;
}
return bc;
}
//好后缀分为3种情况:
//1. subStr中有子串匹配好后缀,则subStr中最靠右的与好后缀相同的子串同好后缀对齐;
//2. subStr中没有子串匹配好后缀,但有最大前缀与好后缀靠右子串匹配,则将subStr中的最大匹配前缀与好后缀中相匹配的字符对齐;
//3. 以上两种情况都不存在,则直接向后移动subStr的长度的位置。
//所以需要两个数组用来记录:
//1. 好后缀的最后一个字符之前的字符与好后缀最大长度的关系
//2. 好后缀前的第一个字符与subStr将要移动的步长的关系
int[] Suffixes(char[] subStr)
{
int m = stbStr.Length;
int f = 0;
int g = m-1;
int[] suff = new int[m];
for(int i = 0; i < m; i++)
{
suff[i] = 0;
}
suff[m-1] = m;
for(int i = m-2; i >=0; i--)
{
if(i > g && suff[i+m-1-f] < i-g)
{
suff[i] = suff[i+m-1-f];
}
else
{
if(i < g)
{
g = i;
}
f = i;
while(g>=0 && subStr[g] == subStr[g+m-1-f])
{
g--;
}
suff[i] = f-g;
}
}
return suff;
}
int[] GoodSuffix(char[] subStr)
{
int m = subStr.Length;
int[] suff = Suffixes(subStr);
int[] gc = new int[m];
for(int i = 0; i<m; i++)
{
gs[i] = m;
}
int j = 0;
for(int i = m-1; i>=0; i--)
{
if(suff[i] == i+1)
{
for(j = 0; j<m-1-i; j++)
{
if(gs[j] == m)
{
gs[j] = m-1-i;
}
}
}
}
for(int i = 0; i <= m-2; i++)
{
gs[m-1-suff[i]] = m-1-i;
}
}
坑爹的盗版最后一章讲排序,然后也是大部分都被cut掉了。。。所以接下来以另一本书为教材复习之前没复习到的地方,感觉还挺多的。。。真希望一天能有72个小时。。。意识到光复习理论知识,但是还没有刷过题。。。/(ㄒoㄒ)/~~