LintCode刷題——分割回文串Ⅱ(序列型動態規劃)

題目描述:

給定字符串 s, 須要將它分割成一些子串, 使得每一個子串都是迴文串.數組

最少須要分割幾回?spa

樣例

樣例 1:code

輸入:
"a"
輸出:
0
解釋: 
"a" 自己就是迴文串, 無需分割

樣例 2:blog

輸入:
"aab"
輸出:
1
解釋:
將 "aab" 分割一次, 獲得 "aa" 和 "b", 它們都是迴文串.


思路:

這裏咱們最主要的就是如何判斷出指定區間的字符串爲迴文串,咱們能夠從前日後,以每個字符爲基石,讓其往兩邊伸展,而後考慮奇偶性,由於一個迴文串的長度要麼是奇數,要麼是偶數,就這兩種狀況,因此咱們就能夠定住每個中間字符,向外擴展,判斷這個字符串中哪些區間是迴文串,哪些不是。並用一個二維的布爾類型數組記錄每個區間是否爲迴文串,接下來考慮最後一步就很容易了,咱們知道最後一步必定是從第j個位置分割,將第j + 1個字符到最後一個字符劃分爲一個迴文串,當咱們考慮前i個字符的串是否爲迴文串時,咱們就須要從第一個字符遍歷到第i個字符,從中找到最少分割次數並更新。這樣一來咱們就把考慮前i個字符的串最少分割幾回,轉變爲前j個字符的串最少分割幾回。字符串

轉移方程:f[i] = min{f[i], f[j] + 1}string

 

AC代碼:

 1 public class Solution {
 2     /**
 3      * @param s: A string
 4      * @return: An integer
 5      */
 6     public int minCut(String s) {
 7         // write your code here
 8         if (s == null || s.length() == 0) {
 9             return 0;
10         }
11 
12         char[] c = s.toCharArray();
13         int n = c.length;
14 
15         boolean[][] isPalins = new boolean[n][n];
16 
17         // initialization
18         for (int i = 0; i < n; i++) {
19             for (int j = 0; j < n; j++) {
20                 isPalins[i][j] = false;
21             }
22         }
23 
24         // 定基準
25         for (int t = 0; t < n; t++) {
26             int i, j;
27             // 默認一個字符也是迴文串
28             i = t;
29             j = t;
30 
31             // odd
32             while (i >= 0 && j < n && c[i] == c[j]) {
33                 isPalins[i][j] = true;
34                 i--;
35                 j++;
36             }
37 
38             i = t;
39             j = t + 1;
40             // even
41             while (i >= 0 && j < n && c[i] == c[j]) {
42                 isPalins[i][j] = true;
43                 i--;
44                 j++;
45             }
46         }
47 
48         // 定義狀態:dp[i] 表明前i個字符中迴文串的個數
49         int[] dp = new int[n + 1];
50 
51         // 初始化
52         dp[0] = 0;
53 
54         for (int i = 1; i <= n; i++) {
55             // 由於這裏是取最小值,因此一開始要設爲無窮大
56             // 任意一個字符串(空串除外)都能化成若干個迴文串(由於單個字符就是一個迴文串),因此必定能夠分割出來,即這裏設置爲無窮大也就沒啥問題
57             dp[i] = Integer.MAX_VALUE;
58             // 從第一個字符一直遍歷到第i個字符。挨個判斷,取最小值
59             for (int j = 0; j < i; j++) {
60                 if (isPalins[j][i - 1]) {
61                     // is Palin
62                     dp[i] = Math.min(dp[i], dp[j] + 1);
63                 }
64             }
65         }
66 
67         // 別忘了本題是讓咱們求最小須要分割幾回,全部最後要-1
68         return dp[n] - 1;
69     }
70 }
相關文章
相關標籤/搜索