剪花布条

一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
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;
}
原文地址:https://www.cnblogs.com/qinjames/p/10554693.html