题意
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
题解
KMP
如果匹配成功,指针不用回退。
Hash
分别算出文本串和模式串的hash值,再根据子串进行计算即可。
代码
KMP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int nmax = 100000;
const int INF = 0x3f3f3f3f;
int lent,lens;
char text[nmax],str[nmax];
int nxt[nmax],ans;
void getnext(){
nxt[0] = -1;
int k = -1;
for(int i = 1;i<=lens-1;++i){
while(k>-1 && str[k+1] != str[i]) k = nxt[k];
if(str[k+1] == str[i]) k++;
nxt[i] = k;
}
}
void kmp(){
getnext();
int k = -1;
for(int i = 0;i<=lent-1;++i){
while(k>-1&&str[k+1]!=text[i]) k = nxt[k];
if(str[k+1] == text[i])k++;
if(k==lens-1){
ans ++;
k = -1;
}
}
}
int main(){
while(scanf("%s",text)!=EOF && text[0] !='#'){
ans = 0;
scanf("%s",str);
lens = strlen(str), lent = strlen(text);
kmp();
printf("%d\n",ans);
}
return 0;
}
Hash
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int nmax = 1005;
const int INF = 0x3f3f3f3f;
const ull p = 67;
int lentext,lenstr;
ull texthash[nmax],strhash[nmax],P[nmax];
char text[nmax],str[nmax];
inline void gethash(){
texthash[1] = text[1], strhash[1] = str[1];
for(int i = 2;i<=lentext;++i) texthash[i] = texthash[i-1] * p + text[i];
for(int i = 2;i<=lenstr;++i) strhash[i] = strhash[i-1] * p + str[i];
}
inline ull subhash(int l,int r){
return texthash[r] - texthash[l-1] * P[r-l+1];
}
int main(){
P[1] = p;
for(int i = 2;i<=1001;++i) P[i] = P[i-1] * p;
while(scanf("%s",text+1)){
if(text[1] == '#') break;
scanf("%s",str+1);
lentext = strlen(text+1), lenstr = strlen(str+1);
gethash();
int l = 1,ans=0;
while(1){
int r = l+lenstr-1;
if(subhash(l,r) == strhash[lenstr]){
ans++;
l = r+1;
}else l++;
if(l>lentext - lenstr+1) break;
}
printf("%d\n",ans);
}
return 0;
}