HDU - 2087 - 剪花布条(kmp )

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

Sample Output
0
3

这个题目其实不用kmp做也可以,忘记当时怎么做出来的了,现在在练习kmp,就拿来练练手,其实就是套用模板吧,很简单。
kmp解释1
kmp解释2
kmp就我理解的话,其实就是记录与当前位置重复的前面字符串的末位置。在搜索的过程中便将那些不必要搜索的字符直接跳过去了。
AC代码:

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5 + 5;
int next[maxn];

void init_next(const char *str, int len)
{
    int str_front = 0;
    next[0] = 0;
    for(int cur = 1; cur < len; cur++)
    {
        while(str_front > 0 && str[str_front] != str[cur])  //如果当前的与记录的不相等并且记录的位置大于0的时候就一直往前找
            str_front = next[str_front];
        next[cur] = str_front;     //记录该位置与其重复的上一个位置
        if(str[str_front] == str[cur])  //如果这两个点相等,那么算作是一对重复的子串,下一次则比较下一个字符,所以位置后移
          str_front++;
    }
}

int kmp(const char *match, int ma_len, const char *pattern, int pa_len)
{
    init_next(pattern, pa_len); //初始化next数组
    int pa_cur = 0, num_son = 0;    //num_son统计子串的数量
    for(int ma_cur = 0; ma_cur < ma_len; ma_cur++)
    {
        while(pa_cur > 0 && match[ma_cur] != pattern[pa_cur])
            pa_cur = next[pa_cur];
        if(match[ma_cur] == pattern[pa_cur])
            if(pa_cur == pa_len - 1)    //如果达到子串长度的话,结果加一,当前子串位置重置为0
            {
                num_son++;
                pa_cur = 0;
            }
            else
                pa_cur++;
    }
    return num_son;
}

int main()
{
    char match[maxn], pattern[maxn];
    while(scanf("%s", match), match[0] != '#')
    {
        scanf("%s", pattern);
        int ma_len = strlen(match);
        int pa_len = strlen(pattern);
        int ans = kmp(match, ma_len, pattern, pa_len);
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40788897/article/details/82945030
今日推荐