题目链接http://codeforces.com/problemset/problem/1163/D
题意:
给出一个字符串s由小写字母和星号组成,字符串a和b仅由小写字母组成。
星号可变成任意一个字符,问字符串a在s中出现的次数与b出现的次数之差最大是多少。
题解:
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示第i位,匹配了字符串a j位,字符串b k位的答案。
利用KMP的next数组更新。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+7;
void getnex(char s[N],int nex[N],int n){
int i=0,j=-1;
nex[0]=-1;
while(i<n){
if(j==-1||s[i]==s[j]) i++,j++,nex[i]=j;
else j=nex[j];
}
}
int dp[N][60][60];
char s[N],a[N],b[N];
int na[N],nb[N];
int main(){
scanf("%s%s%s",s,a,b);
int sn=strlen(s),sa=strlen(a),sb=strlen(b);
getnex(a,na,sa);
getnex(b,nb,sb);
memset(dp,-125,sizeof(dp));
dp[0][0][0]=0;
for(int i=1;i<=sn;i++){
if(s[i-1]=='*'){
for(int j=0;j<=sa;j++){
for(int k=0;k<=sb;k++){
for(char c='a';c<='z';c++){
int dj=j,dk=k;
while(c!=a[dj]&&dj!=-1) dj=na[dj];
while(c!=b[dk]&&dk!=-1) dk=nb[dk];
dj++;dk++;
int tmp=dp[i-1][j][k];
if(dj==sa) tmp++;
if(dk==sb) tmp--;
dp[i][dj][dk]=max(dp[i][dj][dk],tmp);
}
}
}
}
else{
for(int j=0;j<=sa;j++){
for(int k=0;k<=sb;k++){
char c=s[i-1];
int dj=j,dk=k;
while(c!=a[dj]&&dj!=-1) dj=na[dj];
while(c!=b[dk]&&dk!=-1) dk=nb[dk];
dj++;dk++;
int tmp=dp[i-1][j][k];
if(dj==sa) tmp++;
if(dk==sb) tmp--;
dp[i][dj][dk]=max(dp[i][dj][dk],tmp);
}
}
}
}
int ans=-(int)1e9;
for(int i=0;i<=sa;i++){
for(int j=0;j<=sb;j++){
ans=max(ans,dp[sn][i][j]);
}
}
printf("%d\n",ans);
}
/*
abc
abc
zzz
*/