UVa 11584 - Partitioning by Palindromes(線性DP + 預處理)
阿新 • • 發佈:2018-03-15
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 + 預處理)