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;
}

猜你喜欢

转载自www.cnblogs.com/cjjsb/p/8954879.html
POJ