KMP算法:HDU-2087-剪花布条

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=2087

HDU-2087-剪花布条
Oil Deposits Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 34671 Accepted Submission(s): 21108

Problem Description
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?

Input
输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。

Output
输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。

Sample Input

abcde a3
aaaaaa aa

Sample Output

0
3


题目的意思是求一个字符串a中包含多少个子串b,除了暴力的二层循环查找外,还可以采用KMP算法

KMP算法是一种改的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

KMP的核心:PMT(Partical Match Table)部分匹配表,也就是求nexts数组
PMT里面的值代表了前缀与后缀的集合交集中元素的最大长度
这里采用模式串自己与自己匹配求得PMT


AC代码:

#include <iostream>
using namespace std;

const int MAXN = 1010;
int nexts[MAXN];

void getnext(string a)          
{                               
    nexts[0]=-1;               
    int i=0,j=-1;
    while(i<a.length())
    {
        if(j==-1||a[i]==a[j])
        {
            i++;j++;
            nexts[i]=j;
        }
        else
        {
            j=nexts[j];        
        }
    }

}

int KMP(string a,string b)
{
    int ans=0;
    int i=0,j=0;

    while(i<a.length())
    {
        if(j==-1||a[i]==b[j])
        {
            i++;
            j++;
        }
        else
        {
            j=nexts[j];
        }
        if(j==b.length())
        {
            ans++;
            j=0;
        }
    }

    return ans;
}

int main()
{
    string a,b;
    while(cin>>a&&a[0]!='#')
    {
        cin >> b;
        getnext(b);
        cout << KMP(a,b) << endl;
    }
    return 0;
}

上一篇:【Linux C】作业:文本相加/格子中输出


下一篇:KMP算法