链接:点击打开链接


题解:先处理字符串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;
}