题目链接:
题目
剪花布条
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 35669 Accepted Submission(s): 21736
Problem Description
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
Input
输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
Output
输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
Sample Input
abcde a3
aaaaaa aa
Sample Output
0
3
大体思路
KMP变形题,原始的KMP是返回子串在母串中第一次出现的位置,现在需要在外面再加一层循环去计数,因为这是剪布条,一旦找到就要全部将子串剪完,所以在计数之后的要把母串的指针向后滑动 子串长度 的长度。
代码
#include <iostream>
using namespace std;
void GetNext(string t,int next[])
{
//求出模式串t的next数组值
int j,k;//j扫描t,k记录t[j]之前与t开头相同的字符个数
j=0,k=-1;
next[0]=-1;
int tlen=t.length();
while(j<tlen-1)
{
if(k==-1||t[j]==t[k])
{
j++,k++;//j,k依次移动到下一个字符
next[j]=k;//设置next的值
}
else
k=next[k];//k回溯
}
}
int KMP(string s,string t,int next[])
{
int i=0,j=0,flag,ans=0;
int tlen=t.length();
int slen=s.length();
do
{
while( j<tlen&&i<slen)
{
if(j==-1||s[i]==t[j])
{
i++,j++;
}
else
j=next[j];
}
if(j>=tlen)
{
flag=1;
ans++;
i=i-j+tlen;//母串指针向后滑动
j=0;//子串指针归零
}
else
flag=0;
}
while(flag);
return ans;
}
int main()
{
string s;
string t;
int next[1000];
while(cin>>s)
{
if(s=="#")
return 0;
else
{
cin>>t;
GetNext(t,next);
cout<<KMP(s,t,next)<<endl;
}
}
return 0;
}