• 字符串匹配(2)


    话说,如果普通的字符串匹配,朴素算法也就够用了。遇到image这种情况的话……不如倒着来朴素?(我喜欢乱搞……(逃
    关于其他字符串匹配算法,请参见 字符串匹配(1) ,本篇重点介绍KMP算法。

    Knuth-Morris-Pratt算法

    这种算法的预处理时间复杂度为O(m),匹配时间为O(n),相比上一种算法,这种算法少了一个|Sigma|的时间。

    下面的内容可能并不清晰,我写出来只是做一个总结。这里(Matrix67)的介绍更为详尽。

    我们假设T=abcdefghij…,P=abce

    显然,在朴素算法的情况下,从T[1]匹配到T[4](从1开始计数),发现 大変、無理です 于是尝试从T[2]开始,从T[3]开始,从T[4]开始。

    但是,从T[i]开始的前提条件是P[1]=T[i],显然,T[1]==P[1]!=P[2]!=P[3]!=P[4],既然这样,从T[2],T[3],T[4]开始尝试,都是无用功。

    那我们继续假设T=ababcdefghij…,P=ababe

    从T[1]开始匹配,到T[5]发现匹配失败,此时并不需要从T[2]开始匹配,而应该从T[3]开始。因为P[1..2]==P[3..4]==ab,而到T[5]匹配失败的同时,也说明了T[1..2]==T[3..4]==ab,因此继续让P[1..2]和T[3..4]配对即可

    如此往复,我们发现具体从哪匹配,只取决于P,和T无关,因此引入一个数组,就是恶名昭著的next[]。

    以下只贴出代码,具体内容请参见其他资料。代码是hzwer学长写的,参见这里

    #include<cstdio>
    #include<string>
    #include<iostream>
    using namespace std;
    int p[101];
    int main()
    {
        string a,b;
        cin>>a>>b;
        int n=a.length(),m=b.length();
        a=" "+a;b=" "+b;
        int j=0;
        for(int i=2;i<=m;i++)
        {
                while(j>0&&b[j+1]!=b[i])j=p[j];
                if(b[j+1]==b[i])j++;
                p[i]=j;
                }
        j=0;
        for(int i=1;i<=n;i++)
        {
                while(j>0&&b[j+1]!=a[i])j=p[j];
                if(b[j+1]==a[i])j++;
                if(j==m){printf("%d",i-m+1);break;}
                }
        return 0;
    }
    
  • 相关阅读:
    java例程练习(多态/动态绑定/迟绑定)
    java例程练习(对象转型及instanceof关键字)
    java例程练习(对象类型数据的排序)
    java例程练习(数三退一[用数组模拟])
    SSL协议与数字证书原理
    SSL和数字证书服务慨述(3)
    数字证书介绍
    SSL和数字证书服务慨述(1)
    SSL和数字证书服务慨述(2)
    如何设置word页脚中的总页码
  • 原文地址:https://www.cnblogs.com/Chuckqgz/p/5673567.html
Copyright © 2020-2023  润新知