【问题标题】:Boyer Moore Algorithm Implementation?Boyer Moore 算法实现?
【发布时间】:2011-03-24 18:40:30
【问题描述】:

C 中是否有 Boyer-Moore 字符串搜索算法的工作示例? 我看过一些网站,但它们看起来很糟糕,包括维基百科。

谢谢。

【问题讨论】:

标签: c string-matching boyer-moore


【解决方案1】:

子字符串搜索算法的最佳站点:

http://igm.univ-mlv.fr/~lecroq/string/

【讨论】:

  • 我看过那个网站,但是它的实现非常简洁并且不包含 main,所以我在关注它时遇到了麻烦。
  • 你想做什么?我想不出任何理由你想要将 BM 实现为一个独立的程序,尤其是当你不知道如何自己调用一个简单的函数时,除非你试图把它作为家庭作业和把它当作你自己的工作...
  • 我正在尝试了解它是如何运作的,足以让我自己编程。我在一定程度上理解了基本概念,但是当我坐下来思考如何用 C 实际编写它时,我感到困惑。该代码没有 cmets,我无法理解每个函数的用途,或者我将按什么顺序进行调用等。
  • 查看BM函数。其他函数都是从它调用的,永远不需要单独调用。它的论点很简单:针和干草堆字符串及其长度。
  • 这是我尝试编译时的输出,我的 main 只是对 BM 的基本调用。 pastebin.com/5tuhmRzh 似乎有很多未定义的常量(我不确定它们是什么意思)。还有一些警告和未使用的变量让我想知道这是否是一个无错误的实现。
【解决方案2】:

在 Bob Stout 的Snippets 网站上有几个 Boyer-Moore-Horspool 的实现(包括周日的变体)。据我所知,Ray Gardner 在BMHSRCH.C 中的实现没有错误1,而且绝对是我见过或听说过的最快的。然而,这并不是最容易理解的——他使用了一些相当棘手的代码来使内部循环尽可能简单。我可能有偏见,但我认为我在PBMSRCH.C 中的版本2 更容易理解(虽然肯定会慢一些)。

1 在其限制范围内 - 它最初是为 MS-DOS 编写的,并且可以为提供更多内存的环境使用重写。
2 这不知何故被贴上“Pratt-Boyer-Moore”的标签,但实际上是周日的 Boyer-Moore-Horspool 的变体(虽然我当时不知道也没有发表,但我相信我实际上发明了大约一年周日之前)。

【讨论】:

  • 遗憾的是,据我了解,Horspool 算法与标准 BM 不同。
  • @Blackbinary:不,这不是同一个算法——它是一个简化版本。虽然最初的 B-M 算法在理论上更好(使用较少的比较),但初始设置足够复杂,它通常更慢。
  • 很遗憾,Snippets 网站似乎已不复存在。
  • @DavidConrad:不幸的是,这是真的;它消失了。如果您搜索snip9707.zip,很容易找到(几乎)最新版本的副本。
【解决方案3】:

这是我用很多奇怪的测试用例强调的 C90 实现:

#ifndef MAX
#define MAX(a,b)  ((a > b) ? (a) : (b))
#endif

void  fillBadCharIndexTable (
    /*----------------------------------------------------------------
    function:
       the table fits for 8 bit character only (including utf-8)
    parameters: */
    size_t  aBadCharIndexTable [],
    char const *  const pPattern,
    size_t  const patternLength)
    /*----------------------------------------------------------------*/
{
    size_t  i;
    size_t  remainingPatternLength = patternLength - 1;

    for (i = 0;  i < 256; ++i) {
        aBadCharIndexTable [i] = patternLength;
    }
    for (i = 0;  i < patternLength;  ++i) {
        aBadCharIndexTable [pPattern [i]] = remainingPatternLength--;
    }
}

void  fillGoodSuffixRuleTable (
    /*----------------------------------------------------------------
    function:
       the table fits for patterns of length < 256; for longer patterns ... (1 of)
       - increase the static size
       - use variable length arrays and >= C99 compilers
       - allocate (and finally release) heap according to demand
    parameters: */
    size_t  aGoodSuffixIndexTable [],
    char const *  const pPattern,
    size_t  const patternLength)
    /*----------------------------------------------------------------*/
{
    size_t  const highestPatternIndex = patternLength - 1;
    size_t  prefixLength = 1;

    /* complementary prefix length, i.e. difference from highest possible pattern index and prefix length */
    size_t  cplPrefixLength = highestPatternIndex;

    /* complementary length of recently inspected pattern substring which is simultaneously pattern prefix and suffix */
    size_t  cplPrefixSuffixLength = patternLength;

    /* too hard to explain in a C source ;-) */
    size_t  iRepeatedSuffixMax;

    aGoodSuffixIndexTable [cplPrefixLength] = patternLength;

    while (cplPrefixLength > 0) {
        if (!strncmp (pPattern,  pPattern + cplPrefixLength,  prefixLength)) {
            cplPrefixSuffixLength = cplPrefixLength;
        }

        aGoodSuffixIndexTable [--cplPrefixLength] = cplPrefixSuffixLength + prefixLength++;
    }

    if (pPattern [0] != pPattern [highestPatternIndex]) {
        aGoodSuffixIndexTable [highestPatternIndex] = highestPatternIndex;
    }

    for (iRepeatedSuffixMax = 1;  iRepeatedSuffixMax < highestPatternIndex;  ++iRepeatedSuffixMax) {
        size_t  iSuffix = highestPatternIndex;
        size_t  iRepeatedSuffix = iRepeatedSuffixMax;

        do {
            if (pPattern [iRepeatedSuffix] != pPattern [iSuffix]) {
                aGoodSuffixIndexTable [iSuffix] = highestPatternIndex - iRepeatedSuffix;
                break;
            }

            --iSuffix;
        } while (--iRepeatedSuffix > 0);
    }
}

char const *  boyerMoore (
    /*----------------------------------------------------------------
    function:
       find a pattern (needle) inside a text (haystack)
    parameters: */
    char const *  const pHaystack,
    size_t  const haystackLength,
    char const *  const pPattern)
    /*----------------------------------------------------------------*/
{
    size_t  const patternLength = strlen (pPattern);
    size_t  const highestPatternIndex = patternLength - 1;
    size_t  aBadCharIndexTable [256];
    size_t  aGoodSuffixIndexTable [256];

    if (*pPattern == '\0') {
        return pHaystack;
    }

    if (patternLength <= 1) {
        return strchr (pHaystack,  *pPattern);
    }

    if (patternLength >= sizeof aGoodSuffixIndexTable) {
        /* exit for too long patterns */
        return 0;
    }

    {
        char const *  pInHaystack = pHaystack + highestPatternIndex;

        /* search preparation */
        fillBadCharIndexTable (
            aBadCharIndexTable,
            pPattern,
            patternLength);
        fillGoodSuffixRuleTable (
            aGoodSuffixIndexTable,
            pPattern,
            patternLength);

        /* search execution */
        while (pInHaystack++ < pHaystack + haystackLength) {
            int  iPattern = (int) highestPatternIndex;

            while (*--pInHaystack == pPattern [iPattern]) {
                if (--iPattern < 0) {
                    return pInHaystack;
                }
            }

            pInHaystack += MAX (aBadCharIndexTable [*pInHaystack],  aGoodSuffixIndexTable [iPattern]);
        }
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    相关资源
    最近更新 更多