问题描述: 给定一个字符串s,将s分割成一些子串,使每个子串都是回文串。 返回s所有可能的回文串分割方案。
样例
给出
s = “aab”
返回
[ ["aa","b"], ["a","a","b"] ]
思路:
注意到在判断回文串的过程中,有大量的重复计算,一个回文串的判定是根据其子串是否是回文串来判断的
举个例子,有字符串
“abcba”
其子串
”bcb“
也是一个回文串
自然想到动态规划
解法
维护一个二维数组,两个下标分别代表起始位置,这样一个数组元素就惟一的表示了一个字串是否是回文串,如果对应的字符串是回文串,那么置为1,否则为 -1,初始化为 0 再利用DFS搜索,由于从数组获取了信息,因此搜索过程中发生了剪枝
source code language:java
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
public class solution {
private List<List<String>> cases;
private int[][] map;
private String insideStr;
private Stack<String> list;
public List<List<String>> partition(String s){
if(s==null||s.length() == 0){
return null;
}
map = new int[s.length()][s.length()];
for(int i = 0; i < s.length() ;++i){
for(int j = 0; j<s.length();++j){
map[i][j] = 0;
}
}
insideStr = s;
cases = new ArrayList<>();
list = new Stack<>();
findCase(0);
return cases;
}
public void findCase(int start){
if(start>=insideStr.length()){
cases.add((Stack<String>)list.clone());
return;
}
for(int i = start;i<insideStr.length();++i){
int j = 0;
boolean breakflag = false;
while(start+j<=i-j) {
if (map[start+j][i-j] == 1){
map[start][i] = 1;
break;
}
if(map[start+j][i-j] == -1){
map[start][i] = -1;
breakflag = true;
break;
}
if(insideStr.charAt(start+j)!=insideStr.charAt(i-j)){
map[start+j][i-j] = -1;
map[start][i] = -1;
breakflag = true;
break;
}
j++;
}
if(!breakflag){
map[start][i] = 1;
list.add(insideStr.substring(start, i+1));
findCase(i + 1);
list.pop();
}
}
}
}
|