链接:点击打开链接
题解:先处理字符串t的第i个前缀是否和后缀相同,然后再处理s的i-i+m-1是否是t串,然后dp。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<iostream>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
const int N=1e5+10;
typedef long long ll;
using namespace std;
char a[N],b[N];
int dp[N],dp2[N];
bool pp[N],legal[N];
int main(){
scanf("%s",a+1);
scanf("%s",b+1);
int n=strlen(a+1),m=strlen(b+1);
if(m>n){
cout<<0<<endl;
return 0;
}
int maxl=0;
legal[0]=1;
for(int i=1;i<m;i++){
bool f=1;
for(int j=1;j<=i;j++){
if(b[j]!=b[m-i+j]){
f=0;
break;
}
}
legal[i]=f;//处理前缀和后缀是否相等
}
for(int i=1;i<=n-m+1;i++){
bool f=1;
for(int j=i;j<=i+m-1;j++){
if(a[j]=='?')continue;
if(a[j]!=b[j-i+1]){
f=0;
break;
}
}//判断以i开始的串是否是t这个串
pp[i+m-1]=f;
}
for(int i=1;i<=n;i++){
if(pp[i]){
dp[i]=max(dp[i],dp2[i-m]+1);
for(int j=1;j<m;j++){
if(legal[j])dp[i]=max(dp[i],dp[i-m+j]+1);
}
}
dp2[i]=max(dp[i],dp2[i-1]);
//dp[i]代表i有取的情况,dp2[i]代表到i这个位置最大子串数
}
cout<<dp2[n]<<endl;
return 0;
}