一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
Input
输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
Output
输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
Sample Input
abcde a3
aaaaaa aa
Sample Output
0
3
题目大意:本题输入为多实例,每组测试样例为两串字符,中间用空格隔开,遇到星号停止输入,对于第一个字符串,查找第二个字符串在其中共出现了几次,并输出。
解题思路:再输入每组数据字符串之后,获取这个字符串的next数组,然后判断字符串长度对长度减next[字符串长度]是否为0,如果是0,则输出长度除以长度减next[字符串长度],如果不为0,那就输出1。
错误分析:注意本题字符串二在字符串一中出现的时候不能包含上一次出现的字符,即不能重叠。
#include<bits/stdc++.h>
using namespace std;
char str[1001],ptr[1001];
int Next[1001];
//输出子串在模板串中出现了几次,不可重叠
int slen,plen;
void gtNext()
{
int k=-1;int j=0;
while(j<plen)
{
if(k==-1||ptr[j]==ptr[k])
{
j++;k++;
if(ptr[j]!=ptr[k])//这一步是对next数组的优化,让程序更快一些,本来只有下面一行
Next[j]=k;
else Next[j]=Next[k];//优化后next数组并不是原来的常规值,注意如果题目需要对原next数组进行利用,不建议优化
}
else k=Next[k];
}
return ;
}
int kmp()
{
int i=0;int j=0;
int cnt=0;
while(i<slen&&j<plen)
{
if(j==-1||str[i]==ptr[j])
{
i++;
j++;
}
else j=Next[j];
if(j==plen)
{
cnt++;//出现了就记录一次
j=0;//不能重叠,回到0重新查找
}
}
return cnt;
}
int main()
{
while(cin>>str)
{
if(str[0]=='#') break;
cin>>ptr;
slen=strlen(str);
plen=strlen(ptr);
Next[0]=-1;
gtNext();
cout<<kmp()<<endl;
}
}