• NOI 题库 8471 题解


    8471   切割回文

    描述

    阿福最近对回文串产生了非常浓厚的兴趣。

    如果一个字符串从左往右看和从右往左看完全相同的话,那么就认为这个串是一个回文串。例如,“abcaacba”是一个回文串,“abcaaba”则不是一个回文串。

    阿福现在强迫症发作,看到什么字符串都想要把它变成回文的。阿福可以通过切割字符串,使得切割完之后得到的子串都是回文的。

    现在阿福想知道他最少切割多少次就可以达到目的。例如,对于字符串“abaacca”,最少切割一次,就可以得到“aba”和“acca”这两个回文子串。

    输入
    输入的第一行是一个整数 T (T <= 20) ,表示一共有 T 组数据。
    接下来的 T 行,每一行都包含了一个长度不超过的 1000 的字符串,且字符串只包含了小写字母。
    输出
    对于每组数据,输出一行。该行包含一个整数,表示阿福最少切割的次数,使得切割完得到的子串都是回文的。
    样例输入
    3
    abaacca
    abcd
    abcba
    样例输出
    1
    3
    0
    提示
    对于第一组样例,阿福最少切割 1 次,将原串切割为“aba”和“acca”两个回文子串。
    对于第二组样例,阿福最少切割 3 次,将原串切割为“a”、“b”、“c”、“d”这四个回文子串。
    对于第三组样例,阿福不需要切割,原串本身就是一个回文串。
    划分型DP 
    f[ i ] 表示前 i 个需要切割的次数
     1 #include "bits/stdc++.h"
     2 
     3 using namespace std ;
     4 const int maxN = 1100 ;
     5 const int INF = 2147483647 ;
     6 
     7 int Judge [ maxN ][ maxN ] ;
     8 char s[ maxN ] ;
     9 int f[ maxN ] ;
    10 
    11 inline int gmin ( int x , int y ) { return x < y ? x : y ; } 
    12 
    13 inline void Init ( const int n ) {
    14         for ( int i=1 ; i<=n ; ++i ) Judge[ i ][ i ] = true ;
    15         for(int i=1 ; i<=n ; ++i ) {
    16                 for(int L=0 ; i-L>=1 && i+L<=n ; ++L ) {
    17                         if ( s [ i - L ] != s [ i + L ] ) break;
    18                         else Judge[ i - L ][ i + L ] = true ; 
    19                 }
    20                 for(int L=0 ; i-L>=1 && i+L+1<=n ; ++L ) {
    21                         if ( s [ i - L ] != s [ i + L + 1 ] ) break;
    22                         else Judge[ i - L ][ i + L + 1 ] = true ;
    23                 }
    24         }
    25 }
    26 
    27 int main ( ) {
    28         int T ; 
    29         scanf ( "%d" , &T ) ;
    30         while ( T-- ) {
    31                 memset ( f , 0x7f , sizeof ( f ) ) ;
    32                 memset ( Judge , false , sizeof ( Judge ) ) ;
    33                 scanf ( "%s" , s + 1 ) ;
    34                 int Len = strlen ( s + 1 ) ;
    35                 Init ( Len ) ;
    36                 
    37                 for ( int i=1 ; i<=Len ; ++i ) {
    38                         if ( Judge [ 1 ][ i ] ) {f[ i ] = 0 ; continue ;} 
    39                         for ( int j=1 ; j<i ; ++j ) {
    40                                 if ( Judge[ j + 1 ][ i ] ) {
    41                                         f[ i ] = gmin ( f[ i ] , f[ j ] + 1 ) ;
    42                                 } 
    43                         }
    44                 }
    45                 printf ( "%d
    " , f[ Len ] ) ;
    46         }
    47         return 0 ; 
    48 } 
    View Code

    2016-10-27  12:50:52

  • 相关阅读:
    禅道导出用例模板乱码问题
    安装docker,部署禅道
    清理ubuntu apt中不用的源
    golang和python连接阿里云MongoDB云数据库(解决ReplicaSetNoPrimary错误)
    10分钟使用腾讯轻量应用服务器与frp开启内网穿透实现ssh
    java初学笔记
    elasticsearch相关
    XML转化问题,
    借鉴别人的。做个笔记SourceTree 使用介绍
    SQL 查询数据库是否存在该表该字段该内容
  • 原文地址:https://www.cnblogs.com/shadowland/p/6003554.html
Copyright © 2020-2023  润新知