剪花布条
Posted fangbozhen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剪花布条相关的知识,希望对你有一定的参考价值。
题目描述
给出两个字符串A和B,求A最多同时分成几个互不重叠的B。
思路
单字符串的匹配问题,可以考虑用KMP解决,属于模板题。
首先来介绍一下KMP,KMP是单字符串的匹配算法,即只有一个母串和一个匹配串。在进行匹配时,如果暴力枚举,时间复杂度最坏为O(nm),而KMP可以实现O(n)的时间复杂度。我们考虑对于字符串A的某一位置进行匹配时,暴力我们需要B的每一位置进行配对,而实际上这里有很多状态是多余的,所以KMP的核心就是构造P数组。对于匹配串B,我们用k=P[ j ]表示B[ 1...k ] =B[ j - k + 1...j ],或者说最长公共前后缀。而对于这个P数组,当A字符串的 i 位置与B字符串 j 位置匹配时,我们考虑下一位i+1和j+1,如果匹配就继续,否则 j 就转到 P[ j ]继续匹配,因为显然这样对于匹配串B [ 1...P[ j ] ]仍然是匹配的,即 B [ 1...P[ j ] ] = A [ i - P[ j ] +1...i ]。
现在我们就要想如何求出P数组。首先我们假设P[ 1 ],P [ 2 ] ... P [ i ],考虑求出P[ i + 1 ]。我们可以用类似的方法,把B串既看作母串又看作匹配串,如果当前匹配就增加j,否则就讲j不断往P[ j ]移动,因为之前的P数组都已求出。
这道题唯一要注意的是互不重叠的串,所以匹配完后j要清零。
代码
#include <bits/stdc++.h> using namespace std; char s[1100],s1[1100]; int pre[1100]; int main() { while(~scanf(" %s",s+1)) { if(strlen(s+1)==1&&s[1]==‘#‘)break ; scanf(" %s",s1+1); pre[1]=0; int n=strlen(s+1),m=strlen(s1+1); int j=0; for(int i=1;i<m;i++) { while(j>0&&s1[i+1]!=s1[j+1])j=pre[j]; if(s1[i+1]==s1[j+1])j++; pre[i+1]=j; } int ans=0;j=0; for(int i=0;i<n;i++) { while(j>0&&s[i+1]!=s1[j+1])j=pre[j]; if(s[i+1]==s1[j+1])j++; if(j==m) { ans++; j=0; } } printf("%d ",ans); } return 0; }
以上是关于剪花布条的主要内容,如果未能解决你的问题,请参考以下文章