zoukankan      html  css  js  c++  java
  • 两种简单的字符串匹配算法

    在机试笔记4中的统计子字符串个数题目中,使用了一种时间复杂度为O(n*m)的字符串匹配算法,他也叫暴力匹配算法或者BF算法。在实际的开发中,它却是一个比较常用的字符串匹配算法。原因有以下几点:

    第一,实际的软件开发中,大部分情况下,模式串和主串的长度都不会太长。而且每次模式串与主串中的子串匹配的时候,当中途遇到不能匹配的字符的时候,就可以就停止了,不需要把 m 个字符都比对一下。所以,尽管理论上的最坏情况时间复杂度是 O(n*m),但是,统计意义上,大部分情况下,算法执行效率要比这个高很多。

    第二,朴素字符串匹配算法思想简单,代码实现也非常简单。简单意味着不容易出错,如果有 bug 也容易暴露和修复。在工程中,在满足性能要求的前提下,简单是首选。这也是我们常说的KISS(Keep it Simple and Stupid)设计原则。

    所以,在实际的软件开发中,绝大部分情况下,朴素的字符串匹配算法就够用了。

    一个长为n的主串中去查找长为m的模式串,最多要对比n-m+1个子串与模式串。

    另一个字符串匹配算法叫RK算法,它的算法思想是:

    我们通过哈希算法对主串中的 n-m+1 个子串分别求哈希值,然后逐个与模式串的哈希值比较大小。如果某个子串的哈希值与模式串相等,那就说明对应的子串和模式串匹配了。这里当然会有哈希冲突的可能。

    哈希函数的设计:

        假设字符串只有小写字母,可以把每个子字符串当成一个26进制数,哈希函数就是把这个26进制数转成10进制数。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    double my_hash(string str)
    {
        double sum = 0;
        int j=0;
        for(int i=str.size();i>=0;i--){
            double index = pow(26,j);
            sum+=(str[i]-'a')*index;
            j++;
        }
        return sum;
    }
    
    int main()
    {
        int n;
        int m;
        string  a,b;
        cin >> n>> m;
        getchar();
        getline(cin,a);
        getline(cin,b);
        double* arr = new double[n-m+1];
        for(int i=0;i<n-m+1;i++){
            string c = a.substr(i,m);
            arr[i]=my_hash(c);
        }
        double v = my_hash(b);
        int sum = 0;
        for(int i=0;i<n-m+1;i++){
            if(arr[i]==v)
                sum++;
        }
        cout << sum<< endl;
        return 0;
    }

     当然这个代码还有需要优化的地方,一是计算指数可以变成查表的方式,二是求其十进制时前后两个子串的计算是有交集的。

  • 相关阅读:
    javascript常用继承方式.
    JavaScript异步编程的四种方法
    ajax的五种状态
    js内存泄漏的问题?
    jquery和zepto有何区别?
    nginx+play framework +mongoDB+redis +mysql+LBS实战总结
    百万级PHP网站Poppen.de的架构分享心得
    【Mongodb教程 第一课 补加课1 】windows7 下安装mongodb 开启关闭服务
    【Mongodb教程 第一课补加课2 】MongoDB下,启动服务时,出现“服务没有响应控制功能”解决方法
    【Mongodb教程 第十七课 】MongoDB常用命令 数据库命令 集合操作命令
  • 原文地址:https://www.cnblogs.com/Sunqingyi/p/12638555.html
Copyright © 2011-2022 走看看