0%

palindrome-partitioning-ii

题目描述

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回符合要求的最少分割次数。

题解

使用动态规划的方法,可以利用上次的动态规划判断回文字符串的方法做优化。

dp[i]:前缀子串 s[0:i] (包括索引 i 处的字符)符合要求的最少分割次数

状态转移方程: dp[i] = min(dp[j] + 1 if s[j + 1: i] 是回文 for j in range(i))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int minCut(string s) {
int slen = s.length();
bool **isPali = new bool*[slen];
for (int i = 0; i < slen; i++)
isPali[i] = new bool[slen];
for (int i = 0; i < slen; i++)
isPali[i][i] = 1;
for (int i = 1; i < slen; i++)
isPali[i][i - 1] = 1;
for (int i = 1; i < slen; i++)
{
for (int j = 0; j < slen-i; j++)
{
isPali[j][i + j] = isPali[j + 1][i + j - 1] && (s[j] == s[i + j]);
}
}
int* dp = new int[slen];
for (int i = 0; i < slen; i++)
dp[i] = i;
for (int i = 1; i < slen; i++)
{
if (isPali[0][i])
{
dp[i] = 0;
continue;
}
for (int j = 0; j < i; j++)
{
if (isPali[j + 1][i])
{
dp[i] = min(dp[j] + 1, dp[i]);
}
}
}
return dp[slen - 1];
}

最初是按照上次的想法稍微改动了一下,结果“超出时间限制”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
bool **dp;
int slen = 0;
void dfsHelper(string& s,int ps,int& tmp,int& res)
{
if (tmp > res)return;
if (ps >= slen)
{
res = tmp < res ? tmp : res;
return;
}
for (int i = ps; i < slen; i++)
{
if (dp[ps][i])
{
tmp++;
dfsHelper(s, i + 1, tmp, res);
tmp--;
}
}
}
int minCut(string s) {
slen = s.length();
dp = new bool*[slen];
for (int i = 0; i < slen; i++)
dp[i] = new bool[slen];
for (int i = 0; i < slen; i++)
dp[i][i] = 1;
for (int i = 1; i < slen; i++)
dp[i][i - 1] = 1;
for (int i = 1; i < slen; i++)
{
for (int j = 0; j < slen-i; j++)
{
dp[j][i + j] = dp[j + 1][i + j - 1] && (s[j] == s[i + j]);
}
}
int res = slen, tmp = 0;
dfsHelper(s,0, tmp, res);
return res-1;
}

还是很菜啊……所以更不能一直躺着啊……