1. 程式人生 > >BZOJ3214 [Zjoi2013]麗潔體

BZOJ3214 [Zjoi2013]麗潔體

題解 展開 tdi 練習 har line tchar 作者 註意

題意

平時的練習和考試中,我們經常會碰上這樣的題:命題人給出一個例句,要我們類比著寫句子。這種往往被稱為仿寫的題,不單單出現在小學生的考試中,也有時會出現在中考中。許多同學都喜歡做這種題,因為較其它題顯得有趣。仿寫的句子往往具有“A__B__C”的形式,其中A,B,C是給定的由一個或多個單詞組成的短句,空的部分需要學生填寫。當然,考試的時候空在那裏也是可以的。例如,“其實天不暗陰雲終要散,其實 ,其實 ,其實路不遠一切會如願,艱難困苦的日子裏我為你祈禱,請你保重每一天”。再比如,“見了大海的洶湧,沒見過大山的巍峨,真是遺憾;見了大山的巍峨,沒見過 ,還是遺憾。出發吧,永遠出發。 ,人有不老的心情。”由於現在是網絡時代,我們不再只能仿寫命題人命的題,我們可以仿寫網上各種句子和段落。2011年3月26日,某人在博客上發布了的消息就惹來了很多人的仿寫。

很難過吧。。。考得完爆了。。。
。。。。。。其實也沒什麽可以說的。。。都是蒟蒻的借口罷了。。。
。。。自己果然還只是半吊子水平呢。。。。
。。。祝大家都能進省隊。。。其實只要不要有遺憾就好了呢。。。
雖然我很遺憾或許不能走下去了。。。。。
886

在網絡上廣泛流傳的仿寫,因為在某些地方有獨到之處,大都被命名為“某某體”。打開人人,刷新微博,你也能發現這樣和那樣的體,比如,對不起體,**說明他愛你體等等。金先生註意到了這一現象,他敏銳地認為這是一個很有價值的研究課題,於是就其展開研究,打算發一篇paper。由於在網上發消息,人們有了更大的靈活度,人們有時因為表達的需要,還往原本固定的A, B, C中添加一些修飾的詞語。這就給辨別一個句子或段落是否是另一個句子或段落的仿寫增加了困難。金先生現在研究一種形如“AB

C”的體作品,其中A, B, C分別是某個由若幹單詞組成的短句,*代表0個或多個單詞。他在網上找了大量的體作品,不過很多體作品不太合乎原作者的格式,也就是相當於在正規的體作品中插入了0個或多個單詞。由於數據量太大,金先生無法一個一個看過去,於是想請你幫忙,去掉盡量少的單詞,使它成為指定的體。

分析

參照SFN1036的題解。

A和C顯然只能貪心放,問題在於如何確定B的位置。註意到每個單詞出現次數不超過500,那麽就可以枚舉放的起點,然後暴力往後掃即可。

時間復雜度\(O(500 N)\)

代碼

這題數據有誤……

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*w;
}
template<class T>il T read(rg T&x)
{
    return x=read<T>();
}
typedef long long ll;
using namespace std;

co int N=5e4+1;
int n,t1,t2,t3,s[N],a[N],b[N],c[N];
char buf[N*10];

void init(int s[],int&n)
{
    gets(buf);
    int len=strlen(buf);
    for(int k=0,i=0;i<len;++i)
    {
        if(islower(buf[i]))
            k=k*31+buf[i];
        else
            s[++n]=k,k=0;
    }
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    init(s,n),init(a,t1),init(b,t2),init(c,t3);
    int l=1,r=n,tot=0;
    for(int i=1;i<=t1;++i,++l)while(s[l]!=a[i])++l,++tot;
    for(int i=t3;i>=1;--i,--r)while(s[r]!=c[i])--r,++tot;
    int ans=n;
    for(int i=l;i<=r;++i)if(s[i]==b[1])
    {
        int p=i,flag=0;
        for(int j=1;j<=t2;++j,++p)
        {
            while(p<=r&&s[p]!=b[j])++p;
            if(p>r) {flag=1;break;}
        }
        if(!flag)ans=min(ans,p-i-t2);
    }
    printf("%d\n",ans+tot);
    return 0;
}
/*
xiang yao yi zhi ai zhe mou wu de hua yi yao guai zhi si lai shuo tai chang le xiang yao shi xian yi qie meng xiang de hua yi ren lei zhi sheng lai shuo tai duan le 
yao
tai chang le yao
tai duan le
*/

關於

if(!flag)ans=min(ans,p-i-t2);

我認為應該是

if(!flag)ans=min(ans,p-i+1-t2);

這樣才能過樣例。但是這是WA的。

BZOJ3214 [Zjoi2013]麗潔體