zoukankan      html  css  js  c++  java
  • 【BZOJ3214】[ZJOI2013] 丽洁体(毒瘤字符串读入+动态规划水题)

    点此看题面

    大致题意: 给你一个长句(s)以及三个短句(a,b,c),求至少删去(s)中多少个单词,才能使得到的字符串以(a)为开头,以(c)为结尾,且中间部分还含有一个(b)

    前言

    我觉得我做了假的(ZJOI)(ZJOI)怎么可能这么水。。。

    这是一个我都能推出来的(DP),只可惜挂在了读入。。。

    毒瘤字符串读入

    这道题读入字符串读得我真是想一口@&*&&¥@#【某陈年**】。

    主要是判回车这个地方特别恶心,而且按照我原本的字符串统计方式,在本地是没有问题的,结果一交总会莫名其妙多出一个字符串(后来发现是由于题库上行末是" "两个字符)。

    动态规划水题

    考虑开头和结尾显然贪心,能选就选。

    主要是中间部分,我们可以设(f_x)表示匹配到第(x)个单词所需删除的最少单词数。

    那么假设第(i)个单词可以匹配到(x),第(j)个单词可以匹配到(x-1)(j<i)),则就有转移方程:

    [f_x=f_{x-1}+i-j-1 ]

    然后我们整理一下,发现如果设(g_{x-1})为最小的(f_{x-1}-j-1),就可以得到转移方程:

    [f_x=i+g_{x-1} ]

    (g_x)显然可以在(DP)同时,计算完(f_x)后直接更新。

    然后注意一下每个单词只(DP)自己能匹配到的(x),否则可能会被卡。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define Gmin(x,y) (x>(y)&&(x=(y)))
    using namespace std;
    int m,g[N+5];vector<int> V[N+5];map<string,int> S;
    struct Sentence {int n,v[N+5];}s,a,b,c;
    I void read(Sentence& x)//读入一个句子
    {
    	RI i,l;char c;string ss="";W(true)
    	{
    		if(c=getchar(),c>='a'&&c<='z') ss+=c;//维护单词
    		else if(ss.length()) !S[ss]&&(S[ss]=++m),x.v[++x.n]=S[ss],ss="";//读完了一个单词
    		if(c=='
    ') return;//读到回车退掉
    	}
    }
    int main()
    {
    	RI i,j,sz,l,r,p,res=1e9,ans=0;read(s),read(a),read(b),read(c);
    	for(p=l=1;p<=a.n;++l) s.v[l]==a.v[p]?++p:++ans;//开头
    	for(p=c.n,r=s.n;p;--r) s.v[r]==c.v[p]?--p:++ans;//结尾
    	for(i=1;i<=b.n;++i) g[i]=1e9,V[b.v[i]].push_back(i);//初始化
    	for(i=l;i<=r;++i) for(sz=V[s.v[i]].size(),j=sz-1;~j;--j)//只DP能匹配到的单词
    		p=V[s.v[i]][j]^1?i+g[V[s.v[i]][j]-1]:0,Gmin(g[V[s.v[i]][j]],p-i-1),//计算f,然后更新g
    		V[s.v[i]][j]==b.n&&Gmin(res,p);//统计答案
    	return printf("%d",ans+res),0;//输出答案
    }
    
  • 相关阅读:
    模块之datetime
    模块之time模块
    模块之相对路径导入
    模块之包跨模块导入
    模块
    迭代器
    leetcode234 回文链表(Easy,不简单)
    leetcode543 二叉树的直径(Easy 不简单)
    leetcode538 把二叉树转换为累加树(Easy,不简单)
    leetcode136 只出现一次的数字(Easy)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3214.html
Copyright © 2011-2022 走看看