您的位置:首页 > 其它

POJ 3267 The Cow Lexicon (简单DP)

2015-10-05 16:57 405 查看

题目大意

输入一个长度为m的文本串,n个模板。求在文本串中至少去掉几个字母可以完全匹配模板。(2<= m1<= 300, ≤ n ≤ 600,模板串长度 ≤ 25),全部由小写字母组成。

分析

dp[i]表示以i结尾的子串至少需要去掉字符数

状态转移方程: dp[i] = min(dp[i] , tmp+dp[j]),其中tmp为匹配模板需要去掉的字符数,j是匹配完后的位置。初始化dp[i] = dp[i+1] + 1

对于每个字符c,首先找到模板串中以c开头的模板,然后再逐个匹配,找最佳答案。

代码

#include <iostream>
#include <string>
#include <cstring>
#include <list>

using namespace std;
const int maxn = 1000;
int dp[maxn]; //dp[i]表示从i开始匹配至少要删除的字符数
list<int> lt[26];
string str , s[maxn];

void Init(int n , int m)
{
memset(dp , 0 , sizeof(dp));
for(int i = 0; i < 26; i++) lt[i].clear();
cin >> str;
for(int i = 0; i < n; i++) {
cin >> s[i];
lt[s[i][0]-'a'].push_back(i);
}
}
void match(int k , int x , int m)
{
int len = s[k].length() , i = 0 , j = x , tmp = 0;
while(i < len && j < m) {
if(str[j] == s[k][i]) {i++; j++;}
else {j++; tmp++;}
}
if(i == len) dp[x] = min(dp[x] , tmp + dp[j]);
else dp[x] = min(dp[x] , j - x);
}
int main()
{
int m , n;
while(cin >> n >> m)
{
Init(n , m);
list<int>::iterator it;
// dp[i] = min(dp[i+1] + 1 , tmp + dp[i+len])
for(int i = m-1; i >= 0; i--)
{
int id = str[i] - 'a';  dp[i] = dp[i+1] + 1;
for(it = lt[id].begin(); it != lt[id].end(); it++) match(*it , i , m);
}
cout << dp[0] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: