• 回文串+回溯法 URAL 1635 Mnemonics and Palindromes


    题目传送门

     1 /*
     2     题意:给出一个长为n的仅由小写英文字母组成的字符串,求它的回文串划分的元素的最小个数,并按顺序输出此划分方案
     3     回文串+回溯:dp[i] 表示前i+1个字符(从0开始)最少需要划分的数量,最大值是i+1,即单个回文串;
     4         之前设置ok[j][j+i] 判断从j到j+i的字符是否为回文串(注意两个for的顺序,为满足ok[j][j+i] = ok[j+1][j+i-1])
     5         最后枚举找到最优划分点,用pre[i]记录前一个位置,print函数 输出空格
     6 */
     7 #include <cstdio>
     8 #include <iostream>
     9 #include <algorithm>
    10 #include <cmath>
    11 #include <cstring>
    12 using namespace std;
    13 
    14 const int MAXN = 4e3 + 10;
    15 const int INF = 0x3f3f3f3f;
    16 int dp[MAXN];
    17 int pre[MAXN];
    18 bool ok[MAXN][MAXN];
    19 char s[MAXN];
    20 
    21 void print(int p)
    22 {
    23     if (pre[p] == -1)
    24     {
    25         for (int i=0; i<=p; ++i)    printf ("%c", s[i]);
    26     }
    27     else
    28     {
    29         print (pre[p]);    printf (" ");
    30         for (int i=pre[p]+1; i<=p; ++i)    printf ("%c", s[i]);
    31     }
    32 }
    33 
    34 void work(void)
    35 {
    36     int len = strlen (s);
    37 
    38     for (int i=0; i<len; ++i)
    39     {
    40         for (int j=0; j+i<len; ++j)
    41         {
    42             if (i == 0)    ok[j][j+i] = true;
    43             else if (i == 1)    ok[j][i+j] = (s[j] == s[j+i]);
    44             else if (s[j] == s[j+i])    ok[j][j+i] = ok[j+1][j+i-1];
    45         }
    46     }
    47 
    48     for (int i=0; i<len; ++i)
    49     {
    50         dp[i] = i + 1;    pre[i] = i - 1;
    51         if (ok[0][i])    {dp[i] = 1;    pre[i] = -1;    continue;}
    52         for (int j=i-1; j>=0; --j)
    53         {
    54             if (ok[j+1][i])
    55             {
    56                 if (dp[i] > dp[j] + 1)
    57                 {
    58                     dp[i] = dp[j] + 1;    pre[i] = j;
    59                 }
    60             }
    61         }
    62     }
    63 
    64     printf ("%d
    ", dp[len-1]);
    65     print (len-1);    puts ("");
    66 }
    67 
    68 int main(void)        //URAL 1635 Mnemonics and Palindromes
    69 {
    70     //freopen ("P.in", "r", stdin);
    71 
    72     while (scanf ("%s", s) == 1)
    73     {
    74         memset (ok, false, sizeof (ok));
    75         memset (dp, 0, sizeof (dp));
    76         memset (pre, 0, sizeof (pre));
    77 
    78         work ();
    79     }
    80 
    81     return 0;
    82 }
    编译人生,运行世界!
  • 相关阅读:
    CentOS 7 虚拟机的安装
    2 MySQL rpm
    01-在实体类上加了lombok的@Data注解
    02-myBatisPlus的wrapper接口的使用
    2 MySQL rpm 安装 --下载
    1-MySQL介绍
    MySQL的不归路
    电脑型号4 1500 内存大 机械大硬盘
    电脑型号3 1200 大硬盘
    电脑概览 2 1200 固态SSD
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4492493.html
Copyright © 2020-2023  润新知