題意:給出一個主串,和一本字典,問最少在主串刪除多少字母,可以使其匹配到字典的單詞序列。
分析:從後先前推,dp[i]表示從i到mes結尾需刪除的字符個數。
最壞的情況是 dp[i] = dp[i+1] + 1;
從i開始找與dic[]中的匹配,設 pm是mes[]的下標,如果出現從mes[i] 到 mes[pm] 這一段正好和dic[]裏的一個串匹配,
則 dp[i] = min(dp[i], dp[pm] + pm - i - len)。
pm - i 表示這一段字串的長度,len表示dic[]裏與之匹配的串的長度。pm - i - len 就是[i, pm]段需要刪除的字符個數。
代碼如下:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
string mes;
string dic[605];
int dp[305];
int main()
{
//fstream cin("test.txt");
int n, mes_len;
cin >> n >> mes_len;
cin >> mes;
for (int i = 0; i < n; i++)
cin >> dic[i];
//初始化
for (int i = mes_len; i >= 0; i--)
{
dp[i] = mes_len - i;
}
for (int i = mes_len - 1; i >= 0; i--)
{
dp[i] = dp[i + 1] + 1;
bool flag = 0;
for (int j = 0; j < n; j++) //枚舉字典
{
int dic_len = dic[j].length();
if (dic_len <= mes_len - i&&mes[i] == dic[j][0]) //字典小於i到mes_len的長度
{ //且首字母與mes[i]匹配
int pd = 0; //dic指針
int pm = i; //mes指針
while (pm < mes_len) //逐字符匹配
{
if (mes[pm] == dic[j][pd])
{
pd++;pm++;
}
else
pm++;
if (pd == dic_len)
{
dp[i] = min(dp[i], dp[pm] + pm - i - dic_len);//dp[pm]表示從pm到mes_len刪除的字符數
break; //pm - i - dic_len表示從i到pm需要刪除的字符數
}
}
}
}
}
cout << dp[0] << endl;
//system("pause");
return 0;
}