BF

45 阅读2分钟

串的模式匹配

子串的定位运算通常称为串的模式匹配或串匹配,常见的算法有 BF、RK、KMP、Z 算法等。

设有两个字符串ST,设 S 为主串;T 为子串(模式串)。在主串S中查找与模式T相匹配的子串,如果匹配成功,确定相匹配的子串中的第一个字符在主串S中出现的位置。

BF 算法

最简单直观的模式匹配算法是BF(Brute-Force)算法,该算法依赖于纯粹的计算能力,尝试各种可能性。

例如,假设你有一个小挂锁,有4个数字,每个数字从0-9开始。你忘了密码,但你不想再买一把挂锁。由于您记不住任何数字,因此必须使用蛮力方法来打开锁。

所以你把所有的数字都设置回0,然后一个接一个地尝试:0001、0002、0003,以此类推,直到它打开。在最坏的情况下,需要10000次尝试才能找到你的组合。

BF算法的时间复杂度是 O (n * m)。因此,如果我们使用蛮力在一个由m字符组成的字符串中搜索一个由n字符组成的字符串,那么需要n * m次尝试。

算法步骤

  1. 设指针 ij 指示主串 S 和模式 T 中当前正待比较的字符位置,初始值设为 0。

  2. 若两个串均未比较到串尾,即 ij 均分别小于 ST 的长度:

    • S.ch[i]T.ch[j]比较,若相等,则 ij 分别指示串中下个位置,继续比较后续字符。
    • 若不等,指针后退重新开始匹配,从主串的下一个字符(i = i - j + 1)起再重新和模式的第一个字符(j = 1)比较。
  3. 如果j = T.length,说明模式 T 中的每个字符依次和主串 S 中的一个连续的字符序列相等,匹配成功,返回和模式 T 中第一个字符相等的字符在主串 S 中的序号(i - T.length)

  4. 否则称匹配不成功,返回 -1。

代码实现

/// <summary>
/// BF搜索
/// </summary>
public class BFSearch
{
    /// <summary>
    /// 搜索子串位置
    /// </summary>
    /// <param name="mainString">主串 S</param>
    /// <param name="subString">子串 T</param>
    /// <returns></returns>
    public int SearchSubIndex(string mainString, string subString)
    {
        int i = 0, j = 0;
        while (i < mainString.Length && j < subString.Length)
        {
            if (mainString[i] == subString[j])
            {
                i++;
                j++;
            }
            else
            {
                i = (i - j) + 1;
                j = 0;
            }
        }
        if (j == subString.Length)
            return i - subString.Length;
        else
            return -1;
    }
}

Tests

[TestMethod]
public void BfTest()
{
    var mainString1 = "abcd";
    var subString1 = "cd";
    Assert.IsTrue(_bFSearch.SearchSubIndex(mainString1, subString1) == 2);

    var mainString2 = "aaabb";
    var subString2 = "abc";
    Assert.IsTrue(_bFSearch.SearchSubIndex(mainString2, subString2) == -1);

    var mainString3 = "aaabaaaaab";
    var subString3 = "baaaaab";
    Assert.IsTrue(_bFSearch.SearchSubIndex(mainString3, subString3) == 3);
}

dotnet test

dotnet test --filter ClassName=Algorithm.Tests.BfTests

output

已通过! - 失败:     0,通过:     1,已跳过:     0,总计:     1,持续时间: 8 ms - Algorithm.Tests.dll (net7.0)