题意:给两个字符串s,t s的一些位置的字母任意,问t最多在s上出现几次 (可重叠)
解:
****滚动数组容易忘清空。**
1.上来想到AC自动机,-->只有一个t -->kmp求失配指针。
然后转移就是:
dp[i+1][jnxt]=max(dp[i+1][jnxt],dp[i][j]+(jnxt==lent));
其中第一维长度,第二维是当前长度匹配t的长度多少
2.一直卡在第36点,然后看了别人的代码 。发现比我多一个特判 lent>lens时直接输出0。本人注释掉这个特判,别人的也T了。
分析:把这个特判放在 kmp求失配指针的后边也T了。我不知道求失配指针的复杂度。。。
#include<bits/stdc++.h>
#define en '\n'
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn = 1e5+5;
int rd(){int tem;scanf("%d",&tem);return tem;}
int n,k;
int nxt[maxn];
char s[maxn],t[maxn];
int dp[2][maxn];
int ed[maxn][27];
void kmp(){
//#define int register int
int j=-1,i=0;nxt[0]=-1;int len=strlen(t);
while(i<len){
if(j==-1 or t[i]==t[j]){
i+=1,j+=1,nxt[i]=j;
}else j=nxt[j];
}
for(int i=0;i<=len;++i){
for(int j=0;j<26;++j){
char tem='a'+j;
int tt=i;
while(tem!=t[tt] and tt!=-1)tt=nxt[tt];
tt+=1;
ed[i][j]=tt;
}
}
}
inline int Max(int a,int b){
if(a>b)return a;return b;
}
signed main(){
#ifdef local
freopen("input2.txt","r",stdin);
#endif
#define int register int
scanf("%s",s+1);scanf("%s",t);
int len=strlen(s+1);
int lent=strlen(t);
if(lent>len){
cout<<0<<en;return 0;
}
kmp();
dp[0][0]=1;int ans=1;
for(int i=0;i<len;++i){
bool now=i&1;
bool xia=1-now;
dp[xia][0]=1;
if(s[i+1]=='?'){
for(int j=0;j<=lent;++j){
if(!dp[now][j])continue;
for(int k=0;k<26;++k){
int jnxt=ed[j][k];
dp[xia][jnxt]=Max(dp[xia][jnxt],dp[now][j]+(jnxt==lent));
}
dp[now][j]=0;
}
}else{
for(int j=0;j<=lent;++j){
if(!dp[now][j])continue;
int jnxt=ed[j][s[i+1]-'a'];
dp[xia][jnxt]=Max(dp[xia][jnxt],dp[now][j]+(jnxt==lent));
dp[now][j]=0;
}
}
}
int ind=len&1;
for(int j=0;j<=lent;++j){
ans=Max(ans,dp[ind][j]);
}
cout<<ans-1<<en;
return 0;
}