zoukankan      html  css  js  c++  java
  • Codeforces 852F String Compression

    题目

      OvO http://codeforces.com/contest/825/problem/F

    题解

      KMP+DP

      十分优雅地利用了KMP的fail数组

      fail[k]表示第k个后缀的的fail组数

      dp[i]表示到第i个前缀的最优解

      由于KMP的fail数组中的fail[i]能用来表达这个字符串的第i个前缀的后缀与这个字符串的前缀的最大匹配长度,所以可以用来在O(1)的时间内计算一个字符串整体作行程编码的最短长度。calcu表达了该过程。

      则状态转移方程为 dp[i]=min(dp[i],dp[j]+calcu(j+1,i-(j+1)+1));

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <map>
     7 
     8 using namespace std;
     9 
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 
    13 const int M=8004;
    14 
    15 int lv[M];
    16 int fail[M][M];
    17 char s[M];
    18 int ls;
    19 int dp[M];
    20 
    21 int getLv(int spl)
    22 {
    23     int ret=0;
    24     while(spl)
    25     {
    26         spl/=10;
    27         ret++;
    28     }
    29     return ret;
    30 }
    31 
    32 void init()
    33 {
    34     int i,j,k;
    35     for(i=1;i<=M;i++)
    36         lv[i]=getLv(i);
    37     for(k=0;k<ls;k++)
    38     {
    39         j=-1; fail[k][0]=-1;
    40         for(i=1;k+i<=ls;i++)
    41         {
    42             while(j>=0 && s[k+i-1]!=s[k+j])
    43                 j=fail[k][j];
    44             j++;
    45             fail[k][i]=j;
    46         }
    47     }
    48 //    for(i=0;i<=ls;i++)
    49 //        cout<<fail[0][i]<<' ';
    50 //    cout<<endl;
    51 }
    52 
    53 int calcu(int st,int len)
    54 {
    55     if(len==2 && s[st]==s[st+1])
    56         return 2;
    57     int ret,tmp;
    58     tmp=fail[st][len];
    59 //    cout<<st<<' '<<len<<' '<<tmp<<endl;
    60     if(tmp<(len+1)/2 || len%(len-tmp)!=0)
    61         ret=1+len;
    62     else
    63         ret=lv[len/(len-tmp)]+(len-tmp);
    64     return ret;
    65 }
    66 
    67 void solve()
    68 {
    69     int i,j;
    70     for(i=0;i<ls;i++)
    71     {
    72         dp[i]=min(i+1+1,calcu(0,i+1));
    73         for(j=0;j<i;j++)
    74             dp[i]=min(dp[i],dp[j]+calcu(j+1,i-(j+1)+1));
    75     }
    76     cout<<dp[ls-1]<<endl;
    77 }
    78 
    79 int main()
    80 {
    81     int i,j;
    82     cin>>s;
    83     ls=strlen(s);
    84     init();
    85     solve();
    86     return 0;
    87 }
  • 相关阅读:
    c#格林治时间实现
    K3WISE常用表
    读取单元格数据
    水晶报表使用方法
    vs2010下使用sqlite
    C#执行EXE程序
    SQLLITE HELPER
    SQL LITE安装
    C#多线程
    VS2012 快捷键
  • 原文地址:https://www.cnblogs.com/FxxL/p/7248173.html
Copyright © 2011-2022 走看看