DTOJ #3314. constructive

Posted rensheyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DTOJ #3314. constructive相关的知识,希望对你有一定的参考价值。

【题目描述】

有一个空串,每次可以花费 $a$ 的代价在后面添加一个字母,或花费 $b \times \lvert S \rvert$ 的代价将该串复制一遍放到前面。其中 $\lvert S \rvert$ 为当前字符串长度。

现给定一个字符串 $S$,求构造 $S$ 的最小代价。

【输入格式】

第一行一个字符串 $S$。

第二行两个正整数 $a,b$。

【输出格式】

一行一个正整数表示最小代价。

【样例】

样例输入
aab
3 2

样例输出
8

【数据范围与提示】

字符串长度不超过 $10^6$,$a,b \leq 10^5$。

【题解】

显然直接 $dp$ 即可。

$$f_i=min(f_i-1+a,[i \ mod \ 2==0][str(1,\fraci2)==str(\fraci2+1,i)](f_\fraci2+b\times \fraci2))$$

判断字符串相等可用 $exkmp$ $hash$。

【代码】

#include<bits/stdc++.h>
typedef unsigned long long Hash;
const Hash HASH=13131313;
Hash Pow[1000010],hsh[1000010];
long long f[1000010],a,b;
char S[1000010];
inline Hash check ( int l,int r )  return hsh[r]-hsh[l-1]*Pow[r-l+1]; 
signed main()

    scanf("%s %lld%lld",S+1,&a,&b);
    int n=strlen(S+1);Pow[0]=1;
    for ( int i=1;i<=n;i++ ) Pow[i]=Pow[i-1]*HASH;
    for ( int i=1;i<=n;i++ ) hsh[i]=hsh[i-1]*HASH+S[i];
    for ( int i=1;i<=n;i++ )
    
        f[i]=f[i-1]+a;
        if ( !(i&1) and check(1,i>>1)==check((i>>1)+1,i) ) f[i]=std::min(f[i],f[i/2]+1LL*b*(i/2));
    
    return !printf("%lld\n",f[n]);

 

以上是关于DTOJ #3314. constructive的主要内容,如果未能解决你的问题,请参考以下文章

前端学习(3314):redux的基本操作2

BZOJ 3314 [Usaco2013 Nov]Crowded Cows:单调队列

DTOJ2702:余数

DTOJ2704:数字互换

DTOJ2700:hello world

DTOJ #3194. 去月球