题目描述
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
输入描述
输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
输出描述
输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
测试样例1
输入数据
abcde a3
aaaaaa aa
#
输出数据
0
3
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
#define F first
#define S second
#define PII pair<int, int>
const int N = 3e5 + 10, M = 1e3 + 10, MAX = 1e18, MIN = -1e18, MOD = 998244353;
int n, m, k, v[N], vis[N], p[N];
string a, b;
int kmp(){ // 复杂度 :O(n)
//m为子串的长度, n为母串的长度。(母串里的子串)
int ans = 0, j = 0;
for(int i = 0; i < n; i ++){
while(j > 0 && b[j + 1] != a[i + 1]){
j = p[j]; //不能继续匹配且j还没减到0(减少1的值)
}
if(b[j + 1] == a[i + 1]) j ++; //能继续匹配
if(j == m){
ans ++; // 统计匹配数量
// cout << i - m << endl; //子串在母串的下标
// j = p[j]; //继续寻找匹配(可重叠)
j = 0; //(不可重叠)
}
}
return ans;
}
void pre(){ //p数组预处理
p[1] = 0;
int j = 0;
for(int i = 1; i < m; i ++){ //比较下一个字符不能到 m
while(j > 0 && b[j + 1] != b[i + 1]) j = p[j];
if(b[j + 1] == b[i + 1]) j ++;
p[i + 1] = j; //每趟循坏求的是i+ 1的位置的值。
}
}
signed main(){
IOS
while(cin >> a){
if(a == "#") break;
cin >> b;
m = b.size();
n = a.size();
a = ' ' + a; //下标从1开始
b = ' ' + b;
pre();
cout << kmp() << endl;
}
return 0;
}
标签:cout,int,布条,剪花,cin,++,KMP,define From: https://blog.csdn.net/wxy_27/article/details/140807056