UVa 1630 区间DP Folding
一个字符串如果能简写,要么是重复多次,按题中的要求简写;要么是左右两个部分分别简写后再拼起来。
dp(i, j)表示字串(i, j)所能被简写的最短的字符串。
判断一个字符串是否为周期串以及求出它的周期用的KMP算法。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <string> 6 using namespace std; 7 8 const int maxn = 100 + 10; 9 10 char s[maxn], t[maxn]; 11 string d[maxn][maxn]; 12 13 string ToString(int x) 14 { 15 string ans = ""; 16 while(x) 17 { 18 ans += (char) ('0' + (x % 10)); 19 x /= 10; 20 } 21 reverse(ans.begin(), ans.end()); 22 return ans; 23 } 24 25 int f[maxn]; 26 void getFail(char* s) 27 { 28 int len = strlen(s); 29 f[0] = f[1] = 0; 30 for(int i = 1; i < len; i++) 31 { 32 int j = f[i]; 33 while(j && s[i] != s[j]) j = f[j]; 34 f[i+1] = s[i] == s[j] ? j+1 : 0; 35 } 36 } 37 38 int main() 39 { 40 while(scanf("%s", s) == 1) 41 { 42 int len = strlen(s); 43 for(int i = 0; i < len; i++) d[i][i] = string("") + s[i]; 44 45 for(int l = 2; l <= len; l++) 46 { 47 for(int i = 0; i + l - 1 < len; i++) 48 { 49 int j = i + l - 1; 50 d[i][j] = ""; 51 for(int k = i; k <= j; k++) { d[i][j] += s[k]; t[k-i] = s[k]; } 52 53 t[j - i + 1] = 0; 54 getFail(t); 55 if(l % (l - f[l]) == 0) 56 { 57 int cycle = l - f[l]; 58 string t = ""; 59 t = ToString(l / cycle); 60 t += '('; 61 t += d[i][i + cycle - 1]; 62 t += ')'; 63 64 if(t.length() < d[i][j].length()) d[i][j] = t; 65 } 66 67 for(int k = i; k < j; k++) 68 { 69 if(d[i][k].length() + d[k+1][j].length() < d[i][j].length()) 70 d[i][j] = d[i][k] + d[k+1][j]; 71 } 72 } 73 } 74 75 cout << d[0][len - 1] << endl; 76 } 77 78 return 0; 79 }