zoukankan      html  css  js  c++  java
  • POJ3267

    从今天开始POJ里的一部分类型的题目就一般不放在一起写了

    一个是太丑,格式麻烦,第二个是以后的题目难度都有所增大,因此一道题可能就要写蛮长

    尤其是DP这一块,以前一直没好好学习,现在从基础的先开始吧

    题意:给你一个较长的长度为L的串,以及W个长度较短的串。现在问你要从较长串中删去最少几个字符,才能使得这个串由那些长度较短的串组成。

    好,题意有点难懂是吧,可以看一下example

    删去那两个d使原串变成browncow,既满足要求

    首先这个问题肯定满足从局部最优可以推到全局最优

    即设f[i]表示先i个字符中最少要删去多少个字符才满足要求

    然后发现f[i]可以从它前面转移:

    f[i]=min(f[i-1]+1,f[j]+work(s(j,i),t[k]))(1<=i<=l;0<=j<i;1<=k<=w)
    

    其中work表示要对s(j,i)删去几个字符才能使s(j,i)等于t[k]

    CODE

    #include<iostream>
    #include<string>
    using namespace std;
    const int INF=1e9;
    int n,m,cnt,f[305];
    string s,t[605];
    inline int get(string t,string s)
    {
    	register int i;
    	int p=0;
    	for (i=0;i<t.size();++i)
    	if (s.find(t[i],p)!=string::npos) p=s.find(t[i],p)+1; else return INF;
    	return s.size()-t.size();
    }
    inline int work(string s)
    {
    	int tot=INF;
    	for (register int i=1;i<=n;++i)
    	tot=min(tot,get(t[i],s));
    	return tot;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	std::ios::sync_with_stdio(false);
    	register int i,j;
    	cin>>n>>m>>s;
    	for (i=1;i<=n;++i)
    	cin>>t[i];
    	for (i=1,f[1]=1;i<=m;++i,f[i]=f[i-1]+1)
    	for (j=0;j<i;++j)
    	{
    		string temp=s.substr(j,i-j);
    		f[i]=min(f[i],f[j]+work(temp));
    	}
    	printf("%d",f[m]);
    	return 0;
    }
    

    但是这样的话时间复杂度爆炸

    然后我们很显然地发现,对于一个串,只需要找到在前面第一个包含它的字串然后转移即可,就可以省去枚举j的那一维

    CODE

    #include<iostream>
    #include<string>
    using namespace std;
    const int INF=1e9;
    int n,m,cnt,f[305];
    string s,t[605];
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	std::ios::sync_with_stdio(false);
    	register int i,j;
    	cin>>n>>m>>s;
    	for (i=1;i<=n;++i)
    	cin>>t[i];
    	for (i=1,f[1]=1;i<=m;++i,f[i]=f[i-1]+1)
    	{
    		for (j=1;j<=n;++j)
    		{
    			int p1=i-1,p2=t[j].size()-1;
    			while (p2>=0&&p1>=0)
    			{
    				if (s[p1]==t[j][p2]) --p2; --p1;
    			}
    			if (p2<0) f[i]=min(f[i],f[p1+1]+i-p1-t[j].size()-1);
    		}
    	}
    	printf("%d",f[m]);
    	return 0;
    }
    
  • 相关阅读:
    Flutter 容器(4)
    Linux 安装maven环境
    ajaxStart、ajaxStop使用注意事项
    jquery里用正则来验证密码,必须包含大小写字母,数字及特殊符号,或最少包含两种
    Nginx 相关介绍(Nginx是什么?能干嘛?配有图片示例)
    常见web攻击总结
    用php的chr和ord函数实现字符串和ASCII码互转
    消息队列设计精要
    mysql索引总结----mysql 索引类型以及创建
    MySQL事务隔离级别详解
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8954879.html
Copyright © 2011-2022 走看看