題目鏈接:https://codeforc.es/contest/1096/problem/D
題目大意:有一個字符串數組,每個位置有一個權值,刪掉這個字符要付出這個位置的字符的權值的代價,字符串中可能包含了 “hard” 字符序列,你要刪掉一些字符使得字符串中不會出現 “hard” 子序列,求最小刪除代價。
題解:考慮 “hard” 字符串,當前字符是 “d” 時,要麼刪掉這個 “d”,要麼在 "har"裏刪使得 形成不了 “har”,“使得形成不了har” 和 形成不了 “hard” 是同一性質的子問題,因此可以 dp。
令 t = “hard”,s 爲原串。 設狀態爲dp[i][j],, 表示前 i 個字符,刪掉一些字符使得不能形成:(“h”,當j = 0;“ha”,當 j = 1;“har”,當 j = 2;“hard”,當 j = 3)。
轉移方程:當 s[i] == t[j] 時:否則:枚舉i,j轉移即可
代碼:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
int n;
char s[maxn];
char t[5] = "hard";
ll a[maxn];
ll dp[maxn][5];
int main() {
scanf("%d",&n);
scanf("%s",s + 1);
for(int i = 1; i <= n; i++)
scanf("%lld",&a[i]);
memset(dp,0,sizeof dp);
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 4; j++) {
dp[i][j] = dp[i - 1][j];
if(j == 0) {
if(s[i] == t[j])
dp[i][j] += a[i];
}
else {
if(s[i] == t[j])
dp[i][j] = min(dp[i - 1][j - 1],dp[i][j] + a[i]);
}
}
}
printf("%lld\n",dp[n][3]);
return 0;
}