思路
用f[i][j][k]表示c的i-1项已经匹配到a[j]和b[k]了。
之后就使用KMP算法
①:若c[i]==’*’,则枚举一下是什么字符,再用KMP,假设KMP后a的索引是pos1,b的索引是pos2,则更新ff[i][pos1][pos2]=max(f[i][pos1][pos2],f[i-1][j][k]+val),val就是用KMP判断是否成功匹配的结果决定的
②:若不为 * ,则直接KMP,不用枚举了
初始化:除了f[0[0][0]外,其他的都为-INF,其他的f[0][j][k]为-INF是因为不可能有这种情况,f[0][0][0]=0是因为之后的f[1][j][k]要用到,不是因为有这种情况。
代码
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int N=60,M=1010,INF=0x3f3f3f3f;
int ne1[N],ne2[N];
char c[M],s[N],t[N];
int len1,len2,len3;
int f[M][N][N];
void init(){
len1=strlen(c+1);
len2=strlen(s+1);
len3=strlen(t+1);
for(int i=2,j=0;i<=len2;i++){
while(j&&s[i]!=s[j+1])j=ne1[j];
if(s[i]==s[j+1])j++;
ne1[i]=j;
}
for(int i=2,j=0;i<=len3;i++){
while(j&&t[i]!=t[j+1])j=ne2[j];
if(t[i]==t[j+1])j++;
ne2[i]=j;
}
}
int main(){
cin >> c+1 >> s+1 >> t+1;
init();
for(int i=0;i<=len1;i++)
for(int j=0;j<=len2;j++)
for(int k=0;k<=len3;k++)
f[i][j][k]=-INF;
f[0][0][0]=0;
for(int i=1;i<=len1;i++){
for(int j=0;j<=len2;j++){
for(int k=0;k<=len3;k++){
if(c[i]=='*'){
for(char ch='a';ch<='z';ch++){
int pos1=j;
int pos2=k;
while(pos1&&ch!=s[pos1+1])pos1=ne1[pos1];
if(ch==s[pos1+1])pos1++;
while(pos2&&ch!=t[pos2+1])pos2=ne2[pos2];
if(ch==t[pos2+1])pos2++;
int cnt=0;
if(pos1==len2)cnt++;
if(pos2==len3)cnt--;
f[i][pos1][pos2]=max(f[i][pos1][pos2],f[i-1][j][k]+cnt);
}
}else{
int pos1=j;
int pos2=k;
while(pos1&&c[i]!=s[pos1+1])pos1=ne1[pos1];
if(c[i]==s[pos1+1])pos1++;
while(pos2&&c[i]!=t[pos2+1])pos2=ne2[pos2];
if(c[i]==t[pos2+1])pos2++;
int cnt=0;
if(pos1==len2)cnt++;
if(pos2==len3)cnt--;
f[i][pos1][pos2]=max(f[i][pos1][pos2],f[i-1][j][k]+cnt);
}
}
}
}
int ans=-INF;
for(int i=0;i<=len2;i++){
for(int j=0;j<=len3;j++){
ans=max(ans,f[len1][i][j]);
}
}
cout << ans;
}