一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
Input
输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
Output
输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
Sample Input
abcde a3
aaaaaa aa
Sample Output
0
3
题意:找出一个字符串中有多少给定的子串
pre[i]的含义是长度为i的子串的最大前缀后缀长度。
(关键是找出pre数组)
顺便写一下最小循环节:
长度为len的字符串的最小循环节为L=(len-pre[len]);
1.如果len%L==0,则说明字符串完全由循环节循环组成,且循环周期为len/L。
2.否则,若要补成完全由循环节循环组成的字符串,则需要
L-len%L=L-(len-L)%L=L-pre[len]%L个字符。
参考大神博客:https://blog.csdn.net/hao_zong_yin/article/details/77455285
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define LL long long
using namespace std;
const int maxn=1e4+10;
const int maxm=1e4+10;
char text[maxn],pattern[maxm];
int pre[maxm];
int ans;
void get_pre(int m)
{
int i=0,j=-1;
pre[0]=-1;
while(i<m)
{
if(j==-1||pattern[i]==pattern[j])
{
i++;
j++;
pre[i]=j;
}
else
j=pre[j];
}
}
void kmp_search()
{
int m=strlen(pattern),n=strlen(text);
get_pre(m);
int i=0,j=0;
while(i<n)
{
if(j==m-1&&text[i]==pattern[j])
{
ans++;
i++;
j=pre[j];
}
if(text[i]==pattern[j])
{
i++;
j++;
}
else
{
j=pre[j];
if(j==-1)
{
j=0;
i++;
}
}
}
}
int main()
{
int flag=0;
while(1)
{
if(flag) getchar();
else
{
flag=1;
}
scanf("%s",text);
if(text[0]=='#')
break;
scanf("%s",pattern);
ans=0;
kmp_search();
printf("%d
",ans);
}
return 0;
}