码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 11584 - Partitioning by Palindromes(线性DP + 预处理)

时间:2018-03-15 22:16:46      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:标记   ref   方法   line   ==   div   amp   最小   can   

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2631

 

题意:

输入一个由小写字母组成的字符串(长度不超过1000),你的任务是把它划分成尽量少的回文串。
例如,racecar本身就是回文串;fastcar只能分成7个单字母的回文串,aaadbccb最少分成3个回文串:aaa, d, bccb。

 

分析:

设d[i]为字符0~i划分成的最小回文串的个数,则d[i] = min{d[j] + 1 | s[j+1~i]是回文串}。
可以先用O(n*n)时间预处理s[i..j]是否为回文串。方法是枚举中心,然后不断向左右延伸,直到左右字符不同为止。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int UP = 1000 + 5;
 7 int d[UP]; // d[i]为前i个字符划分成的最小回文串个数
 8 char s[UP];
 9 bool isp[UP][UP]; // isp[i][j]标记s[i..j]是否为回文串
10 
11 void init(char* s, int len){
12     memset(isp, false, sizeof(isp));
13     for(int t = 1; t <= len; t++){
14         for(int f = t, b = t; 1 <= f && b <= len; f--, b++){
15             if(s[f] == s[b]) isp[f][b] = true;
16             else break;
17         }
18         for(int f = t, b = t + 1; 1 <= f && b <= len; f--, b++){
19             if(s[f] == s[b]) isp[f][b] = true;
20             else break;
21         }
22     }
23 }
24 
25 int main(){
26     int T, len;
27     scanf("%d", &T);
28     while(T--){
29         scanf("%s", s + 1);
30         init(s, len = strlen(s + 1));
31         for(int t = 1; t <= len; t++){
32             d[t] = t;
33             for(int i = 1; i <= t; i++)
34                 if(isp[i][t]) d[t] = min(d[t], d[i-1] + 1);
35         }
36         printf("%d\n", d[len]);
37     }
38     return 0;
39 }

 

UVa 11584 - Partitioning by Palindromes(线性DP + 预处理)

标签:标记   ref   方法   line   ==   div   amp   最小   can   

原文地址:https://www.cnblogs.com/hkxy125/p/8576295.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!