• HDU


    题目链接

    题意:你要打印一段字符串,往尾部添加一个字符需要花费p元,复制一段字符到尾部需要花费q元,求打印完全部字符的最小花费。

    一开始想的贪心,后来发现忘了考虑p<q的情况了,还纳闷怎么不对..(囧)

    设$dp[i]$为打印完前i个字符的最小花费

    第一种转移是$dp[i+1]=min(dp[i+1],dp[i]+p)$,可以直接转移

    第二种转移是$dp[j]=min(dp[j],dp[i]+q)$,对于每个i需要找到最大的j,使得$s[i+1,j]$是$s[1,i]$的子串。说到子串,就自然能想到后缀自动机。我们可以在i右移的同时扩展当前的后缀自动机,然后让j也右移,直到不能转移为止。如果对于每个i都让j从i开始往后走的话复杂度是$O(n^2)$的,会T掉,因此需要改进一下。有一个很巧妙的做法,用尺取的方法,每当i右移的时候,不必让j再从i开始走一遍,而是直接右移,如果不能转移的话,就尝试往父结点走,直到有转移为止,注意mxl(结点子串最大长度)不得小于j-i,否则无法完全覆盖$s[i+1,j]$区间。这样复杂度就是$O(n)$了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=4e5+10,M=26;
     5 char s[N];
     6 int n,fa[N],go[N][M],mxl[N],last,tot,p,q;
     7 ll dp[N];
     8 int newnode(int l) {int u=++tot; mxl[u]=l,memset(go[u],0,sizeof go[u]); return u;}
     9 void add(int ch) {
    10     int p=last,np=last=newnode(mxl[p]+1);
    11     for(; p&&!go[p][ch]; p=fa[p])go[p][ch]=np;
    12     if(!p)fa[np]=1;
    13     else {
    14         int q=go[p][ch];
    15         if(mxl[q]==mxl[p]+1)fa[np]=q;
    16         else {
    17             int nq=newnode(mxl[p]+1);
    18             memcpy(go[nq],go[q],sizeof go[q]);
    19             fa[nq]=fa[q],fa[q]=fa[np]=nq;
    20             for(; p&&go[p][ch]==q; p=fa[p])go[p][ch]=nq;
    21         }
    22     }
    23 }
    24 int main() {
    25     while(scanf("%s%d%d",s,&p,&q)==3) {
    26         n=strlen(s),tot=0;
    27         last=newnode(0);
    28         memset(dp,0x3f,sizeof dp),dp[0]=0;
    29         for(int i=0,j=0,u=1; i<n; add(s[i]-'a'),++i) {
    30             for(; j<n; u=go[u][s[j]-'a'],++j) {
    31                 for(; !go[u][s[j]-'a']&&fa[u]&&mxl[fa[u]]>=j-i; u=fa[u]);
    32                 if(!go[u][s[j]-'a'])break;
    33             }
    34             dp[i+1]=min(dp[i+1],dp[i]+p),dp[j]=min(dp[j],dp[i]+q);
    35         }
    36         printf("%lld
    ",dp[n]);
    37     }
    38     return 0;
    39 }

     后记:我又尝试了使用后缀数组+线段树的方法,复杂度$O(nlogn)$,然而这题时限卡得太死了过不去,QAQ

  • 相关阅读:
    了解自我
    IT技能栈
    客户端的工作不仅仅只是看起来那么简单
    .NET 基础 一步步 一幕幕[XML基础操作]
    .NET 基础 一步步 一幕幕[Winform应用程序]
    .NET 基础 一步步 一幕幕[面向对象之堆、栈、引用类型、值类型]
    .NET 基础 一步步 一幕幕[面向对象之new、this关键字]
    .NET 基础 一步步 一幕幕[面向对象之静态、非静态]
    .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
    .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11349025.html
Copyright © 2020-2023  润新知