poj3267 The Cow Lexicon (dp)

題意:給出一個主串,和一本字典,問最少在主串刪除多少字母,可以使其匹配到字典的單詞序列。

分析:從後先前推,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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章