标签:思路 时间复杂度 mes tps main bre 注意 ble 复杂度
??给出两个字符串\(A\)和\(B\),求\(A\)最多同时分成几个互不重叠的\(B\)。
??单字符串的匹配问题,可以考虑用\(KMP\)解决,属于模板题。
??首先来介绍一下\(KMP\),\(KMP\)是单字符串的匹配算法,即只有一个母串和一个匹配串。在进行匹配时,如果暴力枚举,时间复杂度最坏为\(O(nm)\),而\(KMP\)可以实现\((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\n",ans);
}
return 0;
}
标签:思路 时间复杂度 mes tps main bre 注意 ble 复杂度
原文地址:https://www.cnblogs.com/fangbozhen/p/11788152.html