Leetcode problem solution 131-split palindrome string

Problem Description

Give you a string s, please split s into some substrings so that each substring is a palindrome string. Return all possible splitting schemes for s.

A palindrome is a string that is read both forward and backward.

Example 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

Example 2:

输入:s = "a"
输出:[["a"]]
 

prompt:

1 <= s.length <= 16
s 仅由小写英文字母组成

Problem-solving ideas: backtracking + dynamic programming preprocessing

Since all the splitting schemes of the string s are required, we consider using the search + backtracking method to enumerate all possible splitting methods and make judgments.

Assuming that we currently search for the i-th character of the string, and all the characters at the position s[0...i-1] have been divided into several palindrome strings, and the result of the division has been put into the answer array ans, then we It is necessary to enumerate the right boundary j of the next palindrome string so that s[i...j] is a palindrome string.

Therefore, we can start from i and enumerate j from small to large. For the j value of the current enumeration, we use dynamic programming to determine whether s[i...j] is a palindrome string: if s[i...j] is a palindrome string, then add it to the answer array ans, and Use j+1 as the new i for the next level of search, and remove s[i…j] from ans in the future backtracking.

If we have searched for the last character of the string, then we have found a split method that meets the requirements.

When we are judging whether s[i...j] is a palindrome, we can use the idea provided by leetcode problem 5-the longest palindrome substring .

dp[i][i] = (s[i]==s[j])   abd dp[i][j]				当j-i<=1
dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]      当j-i>1

Implementation code

class Solution {
    
    
    public List<List<String>> lists;    //结果集合
    public List<String> list;       //分割的子串的集合
    public int n;                   //字符串长度
    public boolean f [][];          //判断子串是否为回文串
    public String str;              //目标字符串
    public List<List<String>> partition(String s) {
    
    
        n=s.length();       
        str=s;
        lists=new ArrayList<>();
        list=new ArrayList<>();
        f=new boolean[n][n];
        char []arrStr=s.toCharArray();
        //填充f数组,判断f[i][j]代表的子串是否是回文子串
        for(int i=0;i<n;i++){
    
    
            for(int j=0;j<=i;j++){
    
    
                if((i-j)<=1){
    
    
                    if(arrStr[i]==arrStr[j]){
    
    
                        f[j][i]=true;
                    }
                }else{
    
    
                    if(arrStr[i]==arrStr[j] && f[j+1][i-1]==true){
    
    
                        f[j][i]=true;
                    }
                }
            }
        }
        dfs(0);
        return lists;
    }
    public void dfs(int i){
    
    
        if(i==n){
    
    
            lists.add(new ArrayList<String>(list));
            return ;
        }else{
    
    
            //从i开始,从小到大依次枚举j,对于当前枚举的j值,我们使用f数组来判断它是否为回文子串
            for(int j=i;j<n;j++){
    
    
                //如果是回文子串,那么我们就把其添加到结果集合中,并且以j+1为i继续新的搜索
                if(f[i][j]==true){
    
    
                    list.add(str.substring(i,j+1));
                    dfs(j+1);
                //搜索完成以后,将s[i,j]移出。
                    list.remove(list.size()-1);
                }
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_39736597/article/details/114527262