分割回文串
- leetcode131. 分割回文串
- 题目描述
- 回溯算法 + 动态规划
- 代码演示
- 回文字符串
leetcode131. 分割回文串
题目描述
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = “aab”
输出:[[“a”,“a”,“b”],[“aa”,“b”]]
示例 2:
输入:s = “a”
输出:[[“a”]]
提示:
1 <= s.length <= 16
s 仅由小写英文字母组成
回溯算法 + 动态规划
题目要求是所有分割可能,所以用回溯算法是最好的,
但在用回溯算法前,我们应该先准备好回溯算法要回溯的数据.要回溯什么呢,就是所有是回文的子字符串.
求子字符串就可以用动态规划:
一个直观的做法是,我们先预处理除所有的 f[i][j],f[i][j] 代表 [i, j] 这一段是否为回文串。
预处理 f[i][j] 的过程可以用递推去做。
要想 f[i][j] == true ,必须满足以下两个条件:
f[i + 1][j - 1] == true
s[i] == s[j]
由于状态 f[i][j] 依赖于状态 f[i + 1][j - 1],因此需要我们左端点 i 是从大到小进行遍历;而右端点 j 是从小到大进行遍历。
因此,我们的遍历过程可以整理为:右端点 j 一直往右移动(从小到大),在 j 固定情况下,左端点 i 在 j 在左边开始,一直往左移动(从大到小)
然后开始回溯:
刚开始我们从起点第一个 a 进行搜索:
发现 a 是回文串,先将 a 分割出来,再对剩下的 bababa 进行搜索
发现 aba 是回文串,先将 aba 分割出来,再对剩下的 baba 进行搜索
发现 ababa 是回文串,先将 ababa 分割出来,再对剩下的 ba 进行搜索
发现 abababa 是回文串,先将 abababa 分割出来,再对剩下的 `` 进行搜索
代码演示
class Solution {/*** 分割字符串* @param s* @return*/public List<List<String>> partition(String s) {if (s == null || s.length() < 1){return null;}int n = s.length();boolean[][] f = new boolean[n][n];char[] cs = s.toCharArray();for (int j = 0;j < n;j++){for (int i = j;i >= 0;i--){if (i == j){f[i][j] = true;}else if (j - i == 1){//长度为2 时f[i][j] = cs[i] == cs[j];}else{//长度大于2 时f[i][j] = cs[i] == cs[j] && f[i + 1][j - 1];}}}ArrayList<List<String>> ans = new ArrayList<>();ArrayList<String> cur = new ArrayList<>();dfs(s,0,ans,cur,f);return ans;}public void dfs(String s,int index,List<List<String>> ans,List<String> cur,boolean[][]f){if (index == s.length()){ans.add(new ArrayList<>(cur));}for (int i = index;i < s.length();i++){if (f[index][i]){cur.add(s.substring(index,i + 1));dfs(s,i + 1,ans,cur,f);cur.remove(cur.size() - 1);}}}
}
回文字符串
leetcode5. 最长回文子串