回文串+回溯法 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 }
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4492493.html