• 撸呀撸的左手(KMP+DP)


    题目描述

    撸呀撸很迷茫,因为他的左手总是不受控制,做一些不雅的事情。于是撸呀撸一狠心,决定戒撸。没想到,他的左手受不了寂寞,一闲下来就在键盘上各种乱敲。

    唔,神奇的左手表示,safasfasaafafsfafasffsfsfsffsfddfafdfsfadffafadfafadfadfafadfsfa……

    他发现敲出来的字符串有一定规律:如果将字符串划分成若干部分,那么每部分都可由其子串重复若干次得到。
    “若干次”往往大于1,但也可以为1。小撸想请你算一算:用最优的方法划分字符串,然后将各部分替换成其最短的连续重复子串,得到的字符串的最小长度是多少?

    输入格式

    一行字符,都是英文小写字母。

    输出格式

    一个正整数,是最小长度。

    样例输入

    bababacacac

    样例输出

    5
     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 using namespace std ;
     5 #define inf 0x7fffffff
     6 #define MAXN 5010
     7 int pre[ MAXN ] , f[ MAXN ] , n ;
     8 char s[ MAXN ] , st[ MAXN ] ;
     9 
    10 void kmp( int len ) {
    11     pre[ 1 ] = 0 ;
    12     for ( int i = 1 , j = 0 ; i ++ < len ; ) {
    13         for ( ; j && st[ j + 1 ] != st[ i ] ; j = pre[ j ] ) ;
    14         if ( st[ j + 1 ] == st[ i ] ) ++ j ;
    15         pre[ i ] = j ;
    16     }
    17 }
    18 
    19 int main(  ) {
    20     scanf( "%s" , s + 1 ) ;
    21     n = strlen( s + 1 ) ;
    22     f[ 0 ] = 0 ;
    23     for ( int i = 0 ; i ++ < n ; ) {
    24         f[ i ] = inf ;
    25         int len = 0 ;
    26         for ( int j = i ; j ; -- j ) st[ ++ len ] = s[ j ] ;
    27         kmp( len ) ;
    28         for ( int j = i - 1 ; j >= 0 ; -- j ) {
    29             int l = i - j , cost ;
    30             cost = ( l % ( l - pre[ l ] ) ) ? l : ( l - pre[ l ] ) ;
    31             f[ i ] = min( f[ i ] , f[ j ] + cost ) ;
    32         }
    33     }
    34     printf( "%d " , f[ n ] ) ;
    35     return 0 ;

    36 } 

  • 相关阅读:
    只出现一次的数字
    SpringBoot整合Redis
    MFC 0误差画图
    模仿.NET的序列化机制
    求最大子数组
    让CFrameWnd派生类的对象响应鼠标消息的“变态”方法
    关于chm文件和'#'的惊人发现
    CxImage学习笔记
    C++指针系列
    MFC,C++ 截屏
  • 原文地址:https://www.cnblogs.com/acvc/p/3540346.html
Copyright © 2020-2023  润新知