一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
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;
}