1. 程式人生 > >UVa 11584 - Partitioning by Palindromes(線性DP + 預處理)

UVa 11584 - Partitioning by Palindromes(線性DP + 預處理)

scan i++ 題意 algo 方法 nbsp times spa tca

鏈接:

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 + 預處理)