LeetCode 132.分割回文串II
执行用时 :13 ms, 在所有 Java 提交中击败了71.11%的用户
判断回文串:
回文串分两种:长度为奇数、长度为偶数
考虑生成回文串,长度为奇数的回文串会有一个数作为中心,沿两侧扩展。,长度为偶数的回文串会有一条线作为对称轴,向两侧扩展。
那么找到所有的回文串,将每个字符按奇数长度和偶数长度各生成一轮回文串,新建一个二维数组 sign[i][j]
**,表示从i
到j
是否是回文串
确定状态:
关注最优策略中最后一段回文串,设为S[j..N-1]
,设f[j]
为在j
之前最少可以划分多少个回文串
子问题:
由求S[0..N-1]
的最优策略分解为求S[0..j-1]
的最优策略。
转移方程:
f
[
i
]
=
m
i
n
j
=
0
,
…
,
i
−
1
{
f
[
j
]
+
1
(
S
[
j
.
.
i
−
1
]
是
回
文
串
)
}
f[i] = min_{j=0,…,i-1}\{f[j] + 1(S[j..i-1]是回文串)\}
f[i]=minj=0,…,i−1{f[j]+1(S[j..i−1]是回文串)}
---->
f
[
i
]
=
m
i
n
j
=
0
,
…
,
i
−
1
{
f
[
j
]
+
1
(
s
i
g
n
[
j
]
[
i
−
1
]
=
T
r
u
e
)
}
f[i] = min_{j=0,…,i-1}\{f[j] + 1(sign[j][i-1] = True)\}
f[i]=minj=0,…,i−1{f[j]+1(sign[j][i−1]=True)}
初始条件和边界:
f[0]=0
,最后答案为f[n]-1
,因为原题求的是分割次数,f[]
代表的是回文串个数。
class Solution {
private boolean[][] judge(char []ch)
{
int m=ch.length;
boolean [][]f=new boolean[m][m];
for(int i=0;i<m;i++)
Arrays.fill(f[i],false);
for(int c=0;c<m;c++)\\奇数长度回文串
{
for(int j=c,i=c;i>=0&&j<m&&ch[i]==ch[j];)
{
f[i][j]=true;
i--;j++;
}
}
for(int c=0;c<m;c++)\\偶数长度回文串
{
for(int j=c+1,i=c;i>=0&&j<m&&ch[i]==ch[j];)
{
f[i][j]=true;
i--;j++;
}
}
return f;
}
public int minCut(String s) {
char []ch=s.toCharArray();
int m=ch.length;
if(m==0)
return 0;
boolean [][]sign=judge(ch);
int []f=new int[m+1];
f[0]=0;
for(int i=1;i<=m;i++)\\dp
{
f[i]=Integer.MAX_VALUE;
for(int j=0;j<i;j++)
{
if(sign[j][i-1])
f[i]=Math.min(f[i],f[j]+1);
}
}
return f[m]-1;
}
}