POJ 3267 The Cow Lexicon DP

题目链接:


一道简单的DP题。

题目意思是给一个长度为n的字符串s,以及一个有m个单词的字典,求最少需要在s中删除多少个字符之后,s能够完全用字典里的单词表示。

我的做法是DP,时间复杂度大约是O(n*m)

很容易就能想到将问题划分为这样的子问题:dp[i]表示在前0~i个字符组成的子串中最少删除多少个字符后能过完全用字典里的单词表示。这样一来最后的答案就是dp[n-1]

状态转移方程就是:

dp[i] = dp[i-1] + 1 当没有单词以s[i]结尾屎;

dp[i]=min( dp[i] , dp[j] + i - j - len )  len是单词的长度,遍历每一个以s[i]结尾的单词,并从s[i]开始向前匹配,直到i = -1或者匹配成功,匹配成功的位置是j + 1(在我的代码中用的是k来表示。

 

AC代码:


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string.h>
#define N 700
using namespace std;

string s,c;
int m,n;
int dp[N];
string *dict; 

int main()
{
	int i,j,k,p,a;
	cin>>m>>n;
	cin>>s;
	dict=new string[m];
	for(i=0;i<m;i++)
	{
		cin>>c;
		dict[i]=c;//字典
	}
	dp[0]=1;//初始值 
	for(i=0;i<n;i++)
	{
		if(i!=0)
		dp[i]=dp[i-1]+1;//初始值 
		
		for(j=0;j<m;j++)//枚举每一个单词 
		{
			if(i+1>=dict[j].size()&&dict[j][dict[j].size()-1]==s[i])
			//结尾与s[i]相同,而且长度不超 
			{
				p=dict[j].size()-1;
				k=i;
				while(1)//找到一个与单词j相同的子集 
				{
					while((k+1) && s[k]!=dict[j][p]) k--;
					if(k<0) break;//不存在与单词j相同的子集 
					p--;k--;//位置标记移动 
					if(p<0) break;//找到了 
				}
				if(k++<0&&p>=0) continue;
				//不存在,继续遍历,否则进行状态转移 
				a=dict[j].size();
				if(k>0)
				dp[i]=min(dp[i],dp[k-1]+(i-k+1)-a);
				//转移方程  a为单词j长度 
				else dp[i]=min(dp[i],i-k+1-a);
			}
		}
	}
	cout<<dp[n-1]<<endl;//结果 
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值