跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(78) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) 聊天机器人(10) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) ChatGPT(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) RAG(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 智能体(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) kafka(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) 编程语言(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) RAG架构(3) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

category

Pattern searching is an important problem in computer science. When we do search for a string in a notepad/word file, browser, or database, pattern searching algorithms are used to show the search results.

A typical problem statement would be- 

” Given a text txt[0..n-1] and a pattern pat[0..m-1] where n is the length of the text and m is the length of the pattern, write a function search(char pat[], char txt[]) that prints all occurrences of pat[] in txt[]. You may assume that n > m. “
Examples: 

 

Input: txt[] = “THIS IS A TEST TEXT”

pat[] = “TEST”

Output: Pattern found at index 10

Input: txt[] = “AABAACAADAABAABA”

pat[] = “AABA”

Output: Pattern found at index 0

Pattern found at index 9

Pattern found at index 12

 

In this post, we will discuss the Boyer Moore pattern searching algorithm. Like KMP and Finite Automata algorithms, Boyer Moore algorithm also preprocesses the pattern. 
Boyer Moore is a combination of the following two approaches. 

  1. Bad Character Heuristic 
  2. Good Suffix Heuristic 

Both of the above heuristics can also be used independently to search a pattern in a text. Let us first understand how two independent approaches work together in the Boyer Moore algorithm.

If we take a look at the Naive algorithm, it slides the pattern over the text one by one. KMP algorithm does preprocessing over the pattern so that the pattern can be shifted by more than one. The Boyer Moore algorithm does preprocessing for the same reason. It processes the pattern and creates different arrays for each of the two heuristics. At every step, it slides the pattern by the max of the slides suggested by each of the two heuristics. So, it uses greatest offset suggested by the two heuristics at every step

Unlike the previous pattern searching algorithms, the Boyer Moore algorithm starts matching from the last character of the pattern.
In this post, we will discuss the bad character heuristic and the Good Suffix heuristic in the next post. 

Bad Character Heuristic

The idea of bad character heuristic is simple. The character of the text which doesn’t match with the current character of the pattern is called the Bad Character. Upon mismatch, we shift the pattern until – 

  1. The mismatch becomes a match.
  2. Pattern P moves past the mismatched character.

Case 1 – Mismatch become match 

We will lookup the position of the last occurrence of the mismatched character in the pattern, and if the mismatched character exists in the pattern, then we’ll shift the pattern such that it becomes aligned to the mismatched character in the text T. 

Explanation:

In the above example, we got a mismatch at position 3.

Here our mismatching character is “A”. Now we will search for last occurrence of “A” in pattern. We got “A” at position 1 in pattern (displayed in Blue) and this is the last occurrence of it. Now we will shift pattern 2 times so that “A” in pattern get aligned with “A” in text.

Case 2 – Pattern move past the mismatch character 

We’ll lookup the position of last occurrence of mismatching character in pattern and if character does not exist we will shift pattern past the mismatching character. 

Explanation: 

Here we have a mismatch at position 7.

The mismatching character “C” does not exist in pattern before position 7 so we’ll shift pattern past to the position 7 and eventually in above example we have got a perfect match of pattern (displayed in Green). We are doing this because “C” does not exist in the pattern so at every shift before position 7 we will get mismatch and our search will be fruitless.

Implementation:

In the following implementation, we pre-process the pattern and store the last occurrence of every possible character in an array of size equal to alphabet size. If the character is not present at all, then it may result in a shift by m (length of pattern). Therefore, the bad character heuristic takes O(n/m) time in the best case. 

Below is the implementation of the above idea:

 

/* C++ Program for Bad Character Heuristic of Boyer

Moore String Matching Algorithm */

#include <bits/stdc++.h>

using namespace std;

#define NO_OF_CHARS 256


// The preprocessing function for Boyer Moore's

// bad character heuristic

void badCharHeuristic(string str, int size,

                      int badchar[NO_OF_CHARS])

{

    int i;


    // Initialize all occurrences as -1

    for (i = 0; i < NO_OF_CHARS; i++)

        badchar[i] = -1;


    // Fill the actual value of last occurrence

    // of a character

    for (i = 0; i < size; i++)

        badchar[(int)str[i]] = i;

}


/* A pattern searching function that uses Bad

Character Heuristic of Boyer Moore Algorithm */

void search(string txt, string pat)

{

    int m = pat.size();

    int n = txt.size();


    int badchar[NO_OF_CHARS];


    /* Fill the bad character array by calling

    the preprocessing function badCharHeuristic()

    for given pattern */

    badCharHeuristic(pat, m, badchar);


    int s = 0; // s is shift of the pattern with

               // respect to text

    while (s <= (n - m)) {

        int j = m - 1;


        /* Keep reducing index j of pattern while

        characters of pattern and text are

        matching at this shift s */

        while (j >= 0 && pat[j] == txt[s + j])

            j--;


        /* If the pattern is present at current

        shift, then index j will become -1 after

        the above loop */

        if (j < 0) {

            cout << "pattern occurs at shift = " << s

                 << endl;


            /* Shift the pattern so that the next

            character in text aligns with the last

            occurrence of it in pattern.

            The condition s+m < n is necessary for

            the case when pattern occurs at the end

            of text */

            s += (s + m < n) ? m - badchar[txt[s + m]] : 1;

        }


        else

            /* Shift the pattern so that the bad character

            in text aligns with the last occurrence of

            it in pattern. The max function is used to

            make sure that we get a positive shift.

            We may get a negative shift if the last

            occurrence of bad character in pattern

            is on the right side of the current

            character. */

            s += max(1, j - badchar[txt[s + j]]);

    }

}


/* Driver code */

int main()

{

    string txt = "ABAAABCD";

    string pat = "ABC";

    search(txt, pat);

    return 0;

}


// This code is contributed by rathbhupendra



/* Java Program for Bad Character Heuristic of Boyer

Moore String Matching Algorithm */


class AWQ {


    static int NO_OF_CHARS = 256;


    // A utility function to get maximum of two integers

    static int max(int a, int b) { return (a > b) ? a : b; }


    // The preprocessing function for Boyer Moore's

    // bad character heuristic

    static void badCharHeuristic(char[] str, int size,

                                 int badchar[])

    {


        // Initialize all occurrences as -1

        for (int i = 0; i < NO_OF_CHARS; i++)

            badchar[i] = -1;


        // Fill the actual value of last occurrence

        // of a character (indices of table are ascii and

        // values are index of occurrence)

        for (int i = 0; i < size; i++)

            badchar[(int)str[i]] = i;

    }


    /* A pattern searching function that uses Bad

    Character Heuristic of Boyer Moore Algorithm */

    static void search(char txt[], char pat[])

    {

        int m = pat.length;

        int n = txt.length;


        int badchar[] = new int[NO_OF_CHARS];


        /* Fill the bad character array by calling

           the preprocessing function badCharHeuristic()

           for given pattern */

        badCharHeuristic(pat, m, badchar);


        int s = 0; // s is shift of the pattern with

                   // respect to text

        // there are n-m+1 potential alignments

        while (s <= (n - m)) {

            int j = m - 1;


            /* Keep reducing index j of pattern while

               characters of pattern and text are

               matching at this shift s */

            while (j >= 0 && pat[j] == txt[s + j])

                j--;


            /* If the pattern is present at current

               shift, then index j will become -1 after

               the above loop */

            if (j < 0) {

                System.out.println(

                    "Patterns occur at shift = " + s);


                /* Shift the pattern so that the next

                   character in text aligns with the last

                   occurrence of it in pattern.

                   The condition s+m < n is necessary for

                   the case when pattern occurs at the end

                   of text */

                // txt[s+m] is character after the pattern

                // in text

                s += (s + m < n) ? m - badchar[txt[s + m]]

                                 : 1;

            }


            else

                /* Shift the pattern so that the bad

                   character in text aligns with the last

                   occurrence of it in pattern. The max

                   function is used to make sure that we get

                   a positive shift. We may get a negative

                   shift if the last occurrence  of bad

                   character in pattern is on the right side

                   of the current character. */

                s += max(1, j - badchar[txt[s + j]]);

        }

    }


    /* Driver program to test above function */

    public static void main(String[] args)

    {


        char txt[] = "ABAAABCD".toCharArray();

        char pat[] = "ABC".toCharArray();

        search(txt, pat);

    }

}





<script>
/* Javascript Program for Bad Character Heuristic of Boyer
Moore String Matching Algorithm */
let NO_OF_CHARS = 256;

// A utility function to get maximum of two integers
function max (a,b)
{
    return (a > b)? a: b;
}

// The preprocessing function for Boyer Moore's
// bad character heuristic
function badCharHeuristic(str,size,badchar)
{
    // Initialize all occurrences as -1
    for (let i = 0; i < NO_OF_CHARS; i++)
        badchar[i] = -1;

    // Fill the actual value of last occurrence
    // of a character (indices of table are ascii and values are index of occurrence)
    for (i = 0; i < size; i++)
        badchar[ str[i].charCodeAt(0)] = i;
}

/* A pattern searching function that uses Bad
    Character Heuristic of Boyer Moore Algorithm */
function search(txt,pat)
{
    let m = pat.length;
    let n = txt.length;

    let badchar = new Array(NO_OF_CHARS);

    /* Fill the bad character array by calling
        the preprocessing function badCharHeuristic()
        for given pattern */
    badCharHeuristic(pat, m, badchar);

    let s = 0; // s is shift of the pattern with
                // respect to text
    // there are n-m+1 potential alignments
    while(s <= (n - m))
    {
        let j = m-1;

        /* Keep reducing index j of pattern while
            characters of pattern and text are
            matching at this shift s */
        while(j >= 0 && pat[j] == txt[s+j])
            j--;

        /* If the pattern is present at current
            shift, then index j will become -1 after
            the above loop */
        if (j < 0)
        {
            document.write("Patterns occur at shift = " + s);

            /* Shift the pattern so that the next
                character in text aligns with the last
                occurrence of it in pattern.
                The condition s+m < n is necessary for
                the case when pattern occurs at the end
                of text */
            //txt[s+m] is character after the pattern in text
            s += (s+m < n)? m-badchar[txt[s+m].charCodeAt(0)] : 1;

        }

        else
            /* Shift the pattern so that the bad character
                in text aligns with the last occurrence of
                it in pattern. The max function is used to
                make sure that we get a positive shift.
                We may get a negative shift if the last
                occurrence of bad character in pattern
                is on the right side of the current
                character. */
            s += max(1, j - badchar[txt[s+j].charCodeAt(0)]);
    }
}

/* Driver program to test above function */
let txt="ABAAABCD".split("");
let pat = "ABC".split("");
search(txt, pat);

// This code is contributed by unknown2108
</script>

# Python3 Program for Bad Character Heuristic
# of Boyer Moore String Matching Algorithm

NO_OF_CHARS = 256

def badCharHeuristic(string, size):
    '''
    The preprocessing function for
    Boyer Moore's bad character heuristic
    '''

    # Initialize all occurrence as -1
    badChar = [-1]*NO_OF_CHARS

    # Fill the actual value of last occurrence
    for i in range(size):
        badChar[ord(string[i])] = i

    # return initialized list
    return badChar

def search(txt, pat):
    '''
    A pattern searching function that uses Bad Character
    Heuristic of Boyer Moore Algorithm
    '''
    m = len(pat)
    n = len(txt)

    # create the bad character list by calling
    # the preprocessing function badCharHeuristic()
    # for given pattern
    badChar = badCharHeuristic(pat, m)

    # s is shift of the pattern with respect to text
    s = 0
    while(s <= n-m):
        j = m-1

        # Keep reducing index j of pattern while
        # characters of pattern and text are matching
        # at this shift s
        while j >= 0 and pat[j] == txt[s+j]:
            j -= 1

        # If the pattern is present at current shift,
        # then index j will become -1 after the above loop
        if j < 0:
            print("Pattern occur at shift = {}".format(s))

            ''' 
                Shift the pattern so that the next character in text
                    aligns with the last occurrence of it in pattern.
                The condition s+m < n is necessary for the case when
                pattern occurs at the end of text
            '''
            s += (m-badChar[ord(txt[s+m])] if s+m < n else 1)
        else:
            '''
            Shift the pattern so that the bad character in text
            aligns with the last occurrence of it in pattern. The
            max function is used to make sure that we get a positive
            shift. We may get a negative shift if the last occurrence
            of bad character in pattern is on the right side of the
            current character.
            '''
            s += max(1, j-badChar[ord(txt[s+j])])

# Driver program to test above function
def main():
    txt = "ABAAABCD"
    pat = "ABC"
    search(txt, pat)

if __name__ == '__main__':
    main()

# This code is contributed by Atul Kumar
# (www.facebook.com/atul.kr.007)

 

Output

pattern occurs at shift = 4

Time Complexity : O(m*n)

Auxiliary Space: O(1)

The Bad Character Heuristic may take O(m*n) time in worst case. The worst case occurs when all characters of the text and pattern are same. For example, txt[] = “AAAAAAAAAAAAAAAAAA” and pat[] = “AAAAA”. The Bad Character Heuristic may take O(n/m) in the best case. The best case occurs when all the characters of the text and pattern are different. 

Boyer Moore Algorithm | Good Suffix heuristic

 

文章链接