zoukankan      html  css  js  c++  java
  • DTOJ #3314. constructive

    【题目描述】

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

    现给定一个字符串 $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,frac{i}{2})==str(frac{i}{2}+1,i)](f_{frac{i}{2}}+b imes frac{i}{2}))$$

    判断字符串相等可用 $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
    ",f[n]);
    }
  • 相关阅读:
    类目(分类)
    协议(Protocol)---实例
    OC 复合 组装电脑
    iOS--九宫格奥秘(UIView)(arc4random)
    字符串
    oc 字符串
    七星彩问题
    OC--第一个程序
    关于行内元素垂直居中的一个小小trick
    关于orgChart
  • 原文地址:https://www.cnblogs.com/RenSheYu/p/11330239.html
Copyright © 2011-2022 走看看