给出
n
≤
2
e
3
n\leq2e3
n≤2e3的字符串,并且给出每个字符插入和删除需要的代价,现在要求最少的代价使得这个字符串是个回文串。
删除和插入其实是一回事情,
f
l
,
r
f_{l,r}
fl,r表示
[
l
,
r
]
[l,r]
[l,r]这段区间的最小值,如果
s
i
=
s
j
s_{i}=s_{j}
si=sj,那么
f
l
,
r
=
f
l
+
1
,
r
−
1
f_{l,r}=f_{l+1,r-1}
fl,r=fl+1,r−1,否则
f
i
,
j
=
m
a
x
{
f
i
+
1
,
j
+
w
i
,
f
i
,
j
−
1
+
w
j
}
f_{i,j}=max\{ f_{i+1,j}+w_{i},f_{i,j-1}+w_j\}
fi,j=max{fi+1,j+wi,fi,j−1+wj}。这里的
w
i
w_{i}
wi表示对
i
i
i操作的最小代价,因为在一边插入和在另一边删除是一样的。
这个就当是凑数的吧。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int M=2e3+7;
int add[30],del[30];
char s[M],ch[3];
int f[M][M];
int main() {
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for(int i=1;i<=n;i++) {
scanf("%s",ch+1);
int cur=ch[1]-'a'+1;
scanf("%d%d",&add[cur],&del[cur]);
}
memset(f,0x3f,sizeof(f));
for(int i=1;i<=m;i++) f[i][i]=0;
for(int i=1;i<=m;i++) f[i][i-1]=0;
for(int len=2;len<=m;len++) {
for(int l=1;l+len-1<=m;l++) {
int r=l+len-1;
if(s[l]==s[r]) f[l][r]=f[l+1][r-1];
else f[l][r]=min(f[l+1][r]+min(add[s[l]-'a'+1],del[s[l]-'a'+1]),f[l][r-1]+min(add[s[r]-'a'+1],del[s[r]-'a'+1]));
}
}
printf("%d\n",f[1][m]);
return 0;
}