zoukankan      html  css  js  c++  java
  • HDU 2087剪花布条(KMP入门模板题)

    一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
    Input
    输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
    Output
    输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
    Sample Input
    abcde a3
    aaaaaa aa
    #
    Sample Output
    0
    3

    就是在主串中找子串 ,子串在主串中不重叠。直接套模板。

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
    假设主串为’s[1],s[2]…s[n]’,模式串为’p[1],p[2]…p[m]’。当匹配过程中产生“失配”(即s[i]≠p[j])时,模式串“向右滑动”可行的距离多远。换句话说,当主串中第i个字符与模式中第j个字符“失配”(即比较不等)时,主串中第i个字符(i指针不回溯)应与模式中哪个字符再比较?
    假设此时应与模式中第k(k < j)个字符继续比较,则模式中前k-1个字符的子串必须满足下列关系式①且不可能存在k’< k满足下列关系式①。

                        ①    ‘p[1]p[2]…p[k-1]’=‘s[i-k+1]s[i-k+2]…s[i-1]’
    

    而已经得到的“部分匹配”的结果是

                        ②    ‘p[j-k+1]p[j-k+2]…p[j-1]’=‘s[i-k+1]s[i-k+2]…s[i-1]’
    

    由式①和式②推得下列等式

                        ③    ‘p[1]p[2]…p[k-1]’= ‘p[j-k+1]p[j-k+2]…p[j-1]’
    

    反之,若模式串中存在满足式③的两个子串,则当匹配过程中,主串中第i个字符与模式中第j个字符比较不等时,仅需将模式向右滑动至模式中第k个字符和主串中第i个字符对齐,此时,模式中头k-1个字符的子串‘ p[1]p[2]…p[k-1]’必定与主串中第i个字符之前长度为k-1的子串‘ s[i-k+1]s[i-k+2]…s[i-1]’相等,由此,匹配仅需从模式中第k个字符与主串中第i个字符比较起继续进行。

    Next数组:
    next[i](i从1开始算)代表着,除去第i个数,在一个字符串里面从第一个数到第(i-1)字符串前缀与后缀最长重复的个数。
    构造next数组使用的基本方法是递推,要计算当前第i位字符的next值即计算从字符串开始至第i位前(不包括第i位)的字符串的最长前缀与后缀重复数量。
    规定第0位(第一个字符)的next值是0或-1(有不同构造next函数的方法)。
    第i+1位的next值分两种情况讨论:

    ①当p[i]=p[j]时,前缀和后缀相等,最大长度可以延续因此next[++i]=next[++j]

    ②当p[i]≠p[j]时,前缀和后缀匹配到此不等,那么可以利用已计算好的next值,将j回溯,直至找到可匹配的重复前缀后缀。也就是j=next[j]

    代码如下:

    #include<stdio.h>
    #include<string.h>
    char S[1004],T[1004];
    void kmp_pre(char x[],int m,int next[])///子串预处理next数组
    {
        int i,j;
        j=next[0]=-1;
        i=0;
        while(i<m)
        {
            while(j!=-1&&x[i]!=x[j])j=next[j];
            next[++i]=++j;
        }
    }
    int kmp_count(char x[],int m,char y[],int n)
    {
        int i=0,j=0,next[1004],ans=0;
        kmp_pre(x,m,next);
        while(i<n)
        {
            while(j!=-1&&x[j]!=y[i])j=next[j];
            i++;j++;
            if(j>=m)
            {
                ans++;
                j=0;
            }
        }
        return ans;
    }
    int main()
    {
        while(scanf("%s",S)!=EOF)
        {
            if(S[0]=='#')break;
            scanf("%s",T);
            printf("%d
    ",kmp_count(T,strlen(T),S,strlen(S)));
        }
    }
    
  • 相关阅读:
    Please provide compiled classes of your project with sonar.java.binaries property
    全链路压测
    零宽度短网址生成器
    http://www.easytest.xyz/login_action/
    进程间的五种通信方式介绍
    InteiiJ IDEA中如何制定制定哪一个配置文件
    常见的各种排序算法汇总
    编程面试之前你应该知晓的八大数据结构
    rest-assured-doc接口自动化测试,数据驱动测试平台
    Jenkins 邮件配置 || Jenkins 发送邮件失败,提示:Error sending to the following VALID addresses
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135863.html
Copyright © 2011-2022 走看看