zoukankan      html  css  js  c++  java
  • #1015 : KMP算法

    时间限制:1000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。

    这一天,他们遇到了一只河蟹,于是河蟹就向小Hi和小Ho提出了那个经典的问题:“小Hi和小Ho,你们能不能够判断一段文字(原串)里面是不是存在那么一些……特殊……的文字(模式串)?

    小Hi和小Ho仔细思考了一下,觉得只能想到很简单的做法,但是又觉得既然河蟹先生这么说了,就肯定不会这么容易的让他们回答了,于是他们只能说道:“抱歉,河蟹先生,我们只能想到时间复杂度为(文本长度 * 特殊文字总长度)的方法,即对于每个模式串分开判断,然后依次枚举起始位置并检查是否能够匹配,但是这不是您想要的方法是吧?”

    河蟹点了点头,说道:”看来你们的水平还有待提高,这样吧,如果我说只有一个特殊文字,你能不能做到呢?“

    小Ho这时候还有点晕晕乎乎的,但是小Hi很快开口道:”我知道!这就是一个很经典的模式匹配问题!可以使用KMP算法进行求解!“

    河蟹满意的点了点头,对小Hi说道:”既然你知道就好办了,你去把小Ho教会,下周我有重要的任务交给你们!“

    ”保证完成任务!”小Hi点头道。

    输入

    第一行一个整数N,表示测试数据组数。

    接下来的N*2行,每两行表示一个测试数据。在每一个测试数据中,第一行为模式串,由不超过10^4个大写字母组成,第二行为原串,由不超过10^6个大写字母组成。

    其中N<=20

    输出

    对于每一个测试数据,按照它们在输入中出现的顺序输出一行Ans,表示模式串在原串中出现的次数。

    样例输入

    5
    HA
    HAHAHA
    WQN
    WQN
    ADA
    ADADADA
    BABABB
    BABABABABABABABABB
    DAD
    ADDAADAADDAAADAAD
    样例输出
    3
    1
    3
    1
    0
    提示和题目连接:http://hihocoder.com/problemset/problem/1015
    解答:
    通过查阅资料发现了四种进行字符串匹配的算法,分别为朴素算法、Rabin-Karp、有限自动机算法、Knuth-Morris-Pratt算法

    设定已知条件:已知模式P[1..m]需要匹配的文本T[1..n]
    首先说朴素算法,朴素算法真的很朴素,就是通过一个循环来寻找有效的移位,该循环对n-m+1个可能的每一个移位值s进行匹配检查P[1..m]=T[s+1..s+m]
    算法伪码:
    NAIVE-STRING-MATCHER(T,P)
        n  <- length[T]
        m <- length[P]
        for  s  <- 0 to n-m
            do if P[1..m] = T[s+1..s+m]
                    then print"找到一个匹配的模式"
    

    下面暂时略过Rabin-Karp算法,回头补上,

    有限自动机算法:

      这个算法的步骤就是根据模式P生成一个状态变迁函数,也可以绘出一个状态变迁图

    例如模式P = {ababaca}就是可以定义7个状态

    注:对于长度为n的字符串模式,一般定义n+1个状态,其中包含一个初始状态和一个接受状态,在接受状态意味着一个匹配的成功。

    继续上面模式P的变迁图建立:

      这个是对应于模式P={ababaca}的状态转换图,图中浅蓝的标号0的点为起始状态,红色的标号为0的点为接受状态,图中未画出的输入对应的线均指向状态0.

      在状态0位置,输入a时,此时字符串a的最长后缀对应P的最长前缀字符串a,长度为1,状态转移到1;输入b时,对应的最长前缀字符串长度为0,c时也是

      在状态1位置,输入a时,此时字符串aa的最长后缀对应P的最长前缀字符串为a,长度为1,状态转移到1;输入b时,此时字符串ab的最长后缀对应P的最长前缀字符串为ab,长度为2,所以状态转移到2;当输入c时,字符串ac的最长后缀对应P的最长前缀字符串为空,长度为0,状态转移到0。

      ......

      在状态7位置,到达接受状态,即此时已经出现了一次成功匹配,开始下一轮,再输入一个字符a时状态转移到1,输入b时状态转移到2

    上述即为有限状态机的建立过程,由此可知,当对应模式P的有限状态机建立后,对于文本T的判断是线性的,只需要对于每一个字符输入后的状态变迁,每次到达接受状态就完成一次成功的匹配。

    KMP算法:

      KMP算法的关键在于找到模式P的前缀函数next。

      在此以模式P={ababababca}为例,阐述一下KMP前缀函数的建立意义。

    考察朴素的字符串匹配算法的操作过程,当上述模式当中前四个字符匹配成功后,如果第五个字符匹配失败,说明第文本中对应的第五个字符不是a(建议在纸上画一下),还说明了对应的四个字符为abab,将P右移一个位置发现仍然不匹配,右移两个、三个、四个也是,但是右移五个未必。因此能否不像上述方法那样一步一步右移,而是直接右移五个位置开始进行判断。

    其实在上面匹配过程当中,每次成功的匹配就包含了一定量的信息,而分析模式当中ab的重复也可给人以匹配失败后,可否每次移动两个位置再进行匹配的启发,这样充分发掘模式本身的特点可以建立一个next函数,从而确定每次匹配失败后移动的长度。

    对于上述模式P发掘的next函数为

    伪代码如下:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <vector>
    using namespace std;
    
    int KMP(string t, string p){
      int n = p.size();
      vector <int> next(n+1, 0);
      for(int i=1; i<n; i++){
        int j=i; 
        while(j > 0){
          j = next[j];
          if(p[j] == p[i]){
            next[i+1] = j + 1;
            break;
          }
        }
      }
    
      int ans = 0;
      int m = t.size();
      for(int i=0, j=0; i<m; i++){
        if(j < n && t[i] == p[j])  j++;
        else{
          while(j > 0){
            j = next[j];
            if(t[i] == p[j]){
              j++;
              break;
            }
          }
        }
        if(j == n) 	ans ++;
      }
      return ans;
    }
    
    int main(){
      string t, p;
      int n;
      scanf("%d", &n);
      while(n--){
        cin>>p>>t;
        cout<<KMP(t, p)<<endl;
      }
      return 0;
    }
    

      



    态度决定高度,细节决定成败,
  • 相关阅读:
    atitit.ntfs ext 文件系统新特性对比
    Atitit.图片木马的原理与防范 attilax 总结
    Atitit.图片木马的原理与防范 attilax 总结
    Atitit.jdk java8的语法特性详解 attilax 总结
    Atitit.jdk java8的语法特性详解 attilax 总结
    Atitit.远程接口 监控与木马   常用的api 标准化v2 q216
    Atitit.远程接口 监控与木马   常用的api 标准化v2 q216
    Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结
    Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结
    Atitit.跨平台预定义函数 魔术方法 魔术函数 钩子函数 api兼容性草案 v2 q216  java c# php js.docx
  • 原文地址:https://www.cnblogs.com/lxk2010012997/p/4781899.html
Copyright © 2011-2022 走看看