zoukankan      html  css  js  c++  java
  • 字符串匹配

    •     蛮力查找

        通过穷尽遍历的方式查询,效率最低。

    int force_search(char * s, int sl, char * p, int pl)
    {
        int i(0);
        while ( i + pl <= sl)
        {
            int j(i), k(0);
            while (k < pl)
                if (s[j] == p[k])
                    (j ++, k ++);
                else
                    break;
            if (k == pl)
                return i;
            ++ i;
        }
        return -1;
    }
    •     kmp查找

        kmp算法尽管只有几句代码,但是非常难理解,昨天跟代码走了好几遍,才渐渐晓得主要思想:

        首先分析模式字符串,针对所有的前缀字符串(和全串)获取其所有前缀与后缀字符串的最大公共长度,借助这个长度(即nexts数组)在匹配的时候进行偏移;

    void get_nexts(char * p, int pl, int * nexts)
    {
        int j(0), k(-1);
        nexts[0] = -1;
        while (j < pl)
            if (p[j] == p[k] || k == -1)
                nexts[++ j] = ++ k;
            else
                k = nexts[k];
    }

    对nexts数组进行优化,充分利用当前不匹配的字符,尽最大可能右移nexts数组;

    void get_nexts2(char * p, int pl, int * nexts)
    {
        int j(0), k(-1);
        nexts[0] = -1;
        while (j < pl)
            if (p[j] == p[k] || k == -1)
            {
                (++ j, ++ k);
                nexts[j] = (p[j] != p[k]) ? k : nexts[k];
            }
            else
                k = nexts[k];
    }

        然后逐字符比较,遇到不匹配的只是移动模式字符串的指针(或者int型的索引,指示当前待比较的字符),而主串只是一直往后走;

    int kmp_search(char * s, int sl, char * p, int pl)
    {
        int * nexts = new int[pl + 1];
        get_nexts2(p, pl, nexts);
    
        int i(0), j(0);
        int indexbegin(0);
        while (j < pl && i < sl)
            if (s[i] == p[j])
                (++ i, ++ j);
            else
            {
                indexbegin = i - nexts[j]; 
                0 == j ? ++ i :j = nexts[j];
            }
        delete[] nexts;
        return j == pl ? indexbegin :  -1;
    }
    • 测试
     1     char * mstr = "aaabacaabacaabacabaabb";
     2     char * pstr = "abacab";
     3     
     4 
     5     cout << "========================" << endl;
     6     cout
     7         << force_search(mstr, strlen(mstr), pstr, strlen(pstr))
     8         << endl;
     9     cout
    10         << kmp_search(mstr, strlen(mstr), pstr, strlen(pstr))
    11         << endl;
    12 
    13     for (int i = 0; i < 18; ++ i)
    14     {
    15         pstr = mstr + i;
    16         cout << "========================" << endl;
    17         cout
    18             << force_search(mstr, strlen(mstr), pstr, strlen(pstr))
    19             << endl;
    20         cout
    21             << kmp_search(mstr, strlen(mstr), pstr, strlen(pstr))
    22             << endl;
    23     }
    出自datakv
  • 相关阅读:
    BigDecimal保留几位小数方法及其八种舍入模式
    JAVA 将浮点类型的字符串转换成整数类型 (出现转换异常)
    登录linux服务器,显示为 -bash-4.2$
    linux创建用户并授权
    Linux 磁盘挂载
    ping与 curl与telnet 使用
    Docker运行参容器参数说明
    Docker挂载安装Nginx
    Docker学习
    Linux下 文件存放规范
  • 原文地址:https://www.cnblogs.com/datakv/p/5581488.html
Copyright © 2011-2022 走看看