hdu 2087 剪花布条(KMP)
Posted jpphy0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 2087 剪花布条(KMP)相关的知识,希望对你有一定的参考价值。
问题
hdu 2087 剪花布条 - https://acm.hdu.edu.cn/showproblem.php?pid=2087
分析
- 模式串P的长度为 i i i 的前缀的最长公共前后缀 f [ i ] f[i] f[i]
- f [ 1 ] = 0 f[1]=0 f[1]=0,并设计 f [ 0 ] = − 1 f[0]=-1 f[0]=−1
- 下标从0开始,长度 i i i 前缀的下一个字符下标为 i i i
- 匹配过程中,s的指针不回溯
- 出现不匹配时,则尝试匹配已匹配部分的最长公共前后缀的前缀的下一个字符
代码
/* hdu 2087 剪花布条 */
#include<bits/stdc++.h>
using namespace std;
const int MXN = 10010;
int f[MXN] = {-1}; // f[0] = -1
char s[MXN], p[MXN];
void getfail(){
int i = 0, j = -1; // j从-1开始,则有f[1] = 0
while(p[i]){ // 单循环 表示 二重循环
if(j == -1 || p[i] == p[j]) f[i] = p[++i] == p[++j] ? f[j] : j; // 优化
// if(j == -1 || p[i] == p[j]) f[++i] = ++j; // 无优化
else j = f[j];
}
}
bool kmp(int &offset){ // s从偏移量offset开始匹配
int j = 0;
while(p[j] && s[offset]){
if(p[j] != s[offset]) j = f[j];
else ++offset, ++j;
if(j == -1) ++offset, ++j;
}
return !p[j];
}
int solve(){
int res = 0, offset = 0;
while(kmp(offset)) ++res;
return res;
}
int main(){
while(scanf("%s", s) && s[0] != '#'){
scanf("%s", p), getfail();
printf("%d\\n", solve());
}
return 0;
}
/* hdu 2087 剪花布条 */
#include<bits/stdc++.h>
using namespace std;
const int MXN = 10010;
int f[MXN] = {-1}; // f[0] = -1
char s[MXN], p[MXN];
void getfail(){
int i = 0, j = -1; // j从-1开始,则有f[1] = 0
while(p[i]){ // 单循环 表示 二重循环
if(j == -1 || p[i] == p[j]) f[i] = p[++i] == p[++j] ? f[j] : j; // 优化
// if(j == -1 || p[i] == p[j]) f[++i] = ++j; // 无优化
else j = f[j];
}
}
bool kmp(int &offset){ // s从偏移量offset开始匹配
int j = 0;
while(s[offset] && (j == -1 || p[j])){
if(j == -1 || p[j] == s[offset]) ++offset, ++j;
else j = f[j];
}
return j != -1 && !p[j];
}
int solve(){
int res = 0, offset = 0;
while(kmp(offset)) ++res;
return res;
}
int main(){
while(scanf("%s", s) && s[0] != '#'){
scanf("%s", p), getfail();
printf("%d\\n", solve());
}
return 0;
}
以上是关于hdu 2087 剪花布条(KMP)的主要内容,如果未能解决你的问题,请参考以下文章