• 字符串匹配算法


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define ASCII_SIZE 256
    
    /*一个字符一个字符移动比较*/
    //暴力匹配BF算法
    int BF_BruteForce(char *dest, char *src)
    {
        int i, j;
        
        if (NULL == dest || NULL == src)
        {
            return -1;
        }
        
        int n = (int)strlen(dest);
        int m = (int)strlen(src);
        
        if (n > m)
        {
            return -2;
        }
        
        for (i = 0; i <= m - n; i++)
        {
            if (dest[0] == src[i])
            {
                for (j = 0; j <= n; j++)
                {
                    if (dest[j] != src[j + i])
                    {
                        break;
                    }
                    else if (dest[j + 1] == '')
                    {
                        return 1;
                    }
                }
            }
        }
        
        return 0;
    }
    //RK算法:利用哈希表,每个子字符串为一个哈希值,做比较
    //BM算法
    /*创建坏点哈希表*/
    void BM_CreatBadSpotHash(char dest[], int n, int b[])
    {
        int i;
        for (i = 0; i < ASCII_SIZE; i++)
        {
            b[i] = -1;
        }
        /* 哈希表存储每个字符最后出现的下标 */
        for (i = 0; i < n; i++)
        {
            int asc = (int)dest[i];
            b[asc] = i;
        }
    }
    
    int BM_BoyerMoore_BadSpot(char dest[], int n, char src[], int m)
    {
        int i, j;
        int b[ASCII_SIZE];
        BM_CreatBadSpotHash(dest, n, b);
        i = 0;
        while (i < m - n)
        {
            for (j = n - 1; j >= 0; j--)
            {
                if (dest[j] != src[i + j])
                {
                    break;
                }
            }
            if (j < 0)
            {
                return i;
            }
            else
            {
                //计算移动的距离
                i = i + (j - b[(int)src[i + j]]);
            }
        }
    }
    
    //创建后缀哈希表
    //suffix 存储字符串后缀字符在前面最后一次出现的下标, prefix 存储后缀字符串是否有前缀字符串与之相同
    void BM_CreatSuffixHash(char dest[], int n, int suffix[], int prefix[])
    {
        int i, j;
        int k;
        for (i = 0; i < n; i++)
        {
            suffix[i] = -1;
            prefix[i] = 0;
        }
        //从前往后寻找相同后缀
        for (i = 0; i < n - 1; i++)
        {
            k = 0;
            j = i;
            while ((j >= 0) && (dest[j] == dest[n - k - 1]))
            {
                j--;
                k++;
                suffix[k] = j + 1;
            }
            if (-1 == j)
            {
                prefix[k] = 1;
            }
        }
        
        // for (k = 1; k <= n - 1; k++)
        // {
            // printf("%d, %d
    ", suffix[k], prefix[k]);
        // }
    }
    
    //根据后缀哈希表移动,j表示坏点的下标,n为子串的长度
    int BM_BoyerMoore_GoodSuffix(int j, int n, int suffix[], int prefix[])
    {
        int i;
        //计算后缀个数
        int k = n - j - 1;
        if (suffix[k] != -1)
        {
            //加1表示从坏点后移一个,移动到后缀的第一个字母的下标
            return j - suffix[k] + 1;
        }
        else
        {
            //如果没有后缀,则依次看前缀有几个字符能和后缀匹配上
            for (i = j + 2; i < n - 1; i++)
            {
                if (1 == prefix[n - i])//如果后缀的n - i个字符有对应前缀
                {
                    return i;
                }
            }
        }
    }
    
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    
    int BM_BoyerMoore(char a[], int n, char b[], int m)
    {
        int i, j;
        int x, y;
        
        int bad_spot_hash[ASCII_SIZE];
        BM_CreatBadSpotHash(a, n, bad_spot_hash);
        int suffix[n];
        int prefix[n];
        BM_CreatSuffixHash(a, n, suffix, prefix);
        i = 0;
        while (i < m - n)
        {
            for (j = n - 1; j >= 0; j--)
            {
                if (a[j] != b[i + j])
                {
                    break;
                }
            }
            if (j < 0)
            {
                return i;
            }
    
            x = (j - bad_spot_hash[(int)b[i + j]]);
            
            y = 0;
            
            if (j < n - 1)
            {
                y = BM_BoyerMoore_GoodSuffix(j, n, suffix, prefix);
            }
            
            i = i + max(x, y);
        }
        
        return -1;
    }
    
    #define A_SIZE 4
    #define B_SIZE 10
    /*
    在排序中可以不用坏点排序,直接用后缀,但是用坏点可以提高一定效率
    后缀的本质和坏点相同,只不过是按字符串来移动
    
    */
    int main()
    {
        char a[A_SIZE] = "baaa";
        char b[B_SIZE] = "baaaaaaaaa";
        printf("%d
    ", BM_BoyerMoore(a, A_SIZE, b, B_SIZE));
        //int s[A_SIZE];
        //int p[B_SIZE];
        //BM_CreatSuffixHash(a, A_SIZE, s, p);
        return 0;
    }

    参考链接:

    https://blog.csdn.net/every__day/article/details/86654361

  • 相关阅读:
    字符,字符串,字节
    111
    串口通信
    字符编码
    枚举和结构体
    参数数组
    .Net垃圾回收机制
    try{ } catch{ } finally{ }
    LVS 工作原理图文讲解
    自动化运维工具—Ansible常用模块二
  • 原文地址:https://www.cnblogs.com/zzdbullet/p/10655755.html
Copyright © 2020-2023  润新知