POJ 3267 The Cow Lexicon【題解報告|DP】

題目鏈接

題目大意

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

是匹配單詞序列,而不是一個單詞

思路分析

主要是知道狀態方程的含義

dp[i] 表示從message中第i個字符開始,到第L個字符(結尾處)這段區間所刪除的字符數,初始化爲 dp[L]=0

由於我的程序是從message尾部向頭部檢索匹配,所以是下面的狀態方程:

if(和字典中的某長度爲len的字符匹配成功)dp[i]=min(dp[i],dp[pm]+(pm-i)-len);
else dp[i]= dp[i+1]+1

從程序可以看出,第i個位置到L所刪除的字符數,總是先取最壞情況,只有可以匹配單詞時才進入第二條方程進行狀態優化更新。

第一條方程不難理解,只要弄懂 dp[i] 的意義就能簡單推導

第二條方程難點在 dp[pm]+(pm-i)-len

從程序知道,pm是message的指針(其中i表示當前所匹配的單詞在message中的起始位置),pd是字典的指針

匹配的過程是:

當確認message第i位和某單詞的首位吻合時,就開始逐字匹配,字符相同則兩個指針同時向後移動一次,否則pd固定,pm移動。當因爲 pm>L 跳出匹配時,說明匹配失敗,dp[i]狀態不變;當 pd==單詞長度 時,單詞匹配成功,進行 dp[i] 的狀態優化。

顯然,匹配成功時,pm-i 代表匹配過程中,從位置ipm的區間長度,再減去單詞長度len,則得到從ipm所刪除的字符數(pm-i)-len 。又 dp[pm] 表示從pmL所刪除的字符數(根據檢索方向,dp[pm]的值在此前已經被作爲最壞打算處理,因此並不是空值)

從而 dp[pm]+(pm-i)-len 表示iL刪除的字符數,不難證明這個值一定比 dp[i] 相等或更優,因此取min賦值給 dp[i]

這是本題最難的地方。

最後輸出 dp[0] 就可以了,dp[0] 的意思相信大家都明白了。

#define inf 0x3f3f3f3f
#define vec vector<int>
#define P pair<int,int>
#define ll long long
#define MAX 605

int dp[305], W, L;
string s[MAX], t;

int main() {
	while (scanf("%d %d", &W, &L) != EOF) {
		cin >> t;
		for (int i = 0; i < W; i++)cin >> s[i];

		memset(dp, 0, sizeof(0));
		for (int i = L - 1; i >= 0; i--) {//對每一位進行判斷
			dp[i] = dp[i + 1] + 1;
			for (int j = 0; j < W; j++) {//對字典的每一個串進行判斷
				int len = s[j].size();
				if (L - i >= len && s[j][0]==t[i]) {
					//這一個串可能可以匹配上
					int i1 = i, i2 = 0;
					while (i1 < L&&i2 < len) {
						if (t[i1] == s[j][i2])i2++;
						i1++;
					}
					if (i2 == len)//匹配上了
						dp[i] = min(dp[i], dp[i1] + i1 - i - len);
				}
			}
		}
		cout << dp[0] << endl;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章