LeetCode132 Palindrome Partitioning II


详细见:leetcode.com/problems/palindrome-partitioning-ii


Java Solution: github

package leetcode;

/**
    Given a string s, partition s such that every substring of 
    the partition is a palindrome.
	
	Return the minimum cuts needed for a palindrome partitioning of s.
	
	For example, given s = "aab",
	Return 1 since the palindrome partitioning ["aa","b"] 
	could be produced using 1 cut.
 */

/**
 * @author      zxwtry
 * @email       zxwtry@qq.com
 * @project     OJ
 * @package     leetcode
 * @file        P132_PalindromePartitioningII.java
 * @type        P132_PalindromePartitioningII
 * @date        2016年12月13日 下午7:49:29
 * @details     Solution1: AC 52ms 14.09%
 */
public class P132_PalindromePartitioningII {
	static class Solution {
		public int minCut(String s) {
			if (s == null || s.length() < 2) return 0;
			int[] m = manacher(s);
			int[] ndp = new int[s.length()];
			for (int i = 0; i < s.length(); i ++) {
				if (isPalindrome(m, i, 0)) {
				    ndp[i] = 0;
				    continue;
				}
				ndp[i] = Integer.MAX_VALUE-1;
				for (int j = 1; j <= i; j ++)
					if (isPalindrome(m, i, j))
					    ndp[i] = Math.min(ndp[j-1] + 1, ndp[i]);
			}
			return ndp[ndp.length - 1];
		}
		private boolean isPalindrome(int[] m, int maxIndex, int minIndex) {
			return m[minIndex + maxIndex + 1] > maxIndex - minIndex;
		}
		private int[] manacher(String s) {
		    int mn = 2 * (s == null ? 0 : s.length()) + 1;
			int[] m = new int[mn];
			int ti = 0, ci = 0, mi = 0, li = 0, ri = 0;
			for (int i = 0; i < mn; i ++) {
				mi = 2 * ci - i;
				if (i >= ti || m[mi] == ti-i) {
					li = ri = i;
					while (li-1 > -1 && ri+1 < mn && access(s, li-1) == access(s, ri+1)) {
						li --;
						ri ++;
					}
					ti = ri;
					ci = i;
					m[i] = (ri - li) / 2;
				} else m[i] = Math.min(m[mi], ti-i);
			}
			return m;
		}
		private char access(String s, int i) {
			return i % 2 == 0 ? 0 : s.charAt(i/2);
		}
	}
}


C Solution: github

#pragma warning(disable:4786)
/*
    url: leetcode.com/problems/palindrome-partitioning-ii
    Solution1: TLE
    Solution2: AC 6ms 76.37%
*/

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <stdio.h>

using namespace std;


class Solution1 {
public:
    int _min(int a, int b) {
        return a < b ? a : b;
    }
    int convert(int a, int b) {
        return a * 100000 + b;
    }
    int isP(string& s, int i, int j) {
        while (i < j) {
            if (s[i] != s[j]) return 0;
            i ++;
            j --;
        }
        return 1;
    }
    int minCut(string s) {
        int sn = s.size(), ans = INT_MAX;
        int ** dp = new int* [sn];
        int ** sa = new int* [sn];
        for (int dpi = 0; dpi < sn; dpi ++) {
            dp[dpi] = new int[sn];
            sa[dpi] = new int[sn];
        }
        for (int len = 1; len <= sn; len ++) {
            for (int i = 0; i <= sn - len; i ++) {
                if (s[i] == s[i+len-1] && (len < 3 || (dp[i+1][i+len-2]) == 1988)) {
                    dp[i][i+len-1] = 1988;
                    sa[i][i+len-1] = 1;
                } else {
                    int min_val = INT_MAX;
                    for (int klen = 1; klen < len; klen ++) {
                        min_val = _min(sa[i][i+klen-1] + sa[i+klen][i+len-1], min_val);
                    }
                    sa[i][i+len-1] = min_val;
                }
                
            }
        }
        return sa[0][sn-1]-1;
    }
};

class Solution2 {
public:
    char access(string s, int i) {
        return i%2 == 0 ? '#' : s[i/2];
    }
    int _max(int a, int b) {
        return a < b ? b : a;
    }
    int _min(int a, int b) {
        return a < b ? a : b;
    }
    int* manacher(string& s, int& sn) {
        int nn = 2 * sn + 1;
        int* m = new int[nn];
        int mi = 0, li = 0, ti = 0, left = 0, right = 0;
        for (int i = 0; i < nn; i ++) {
            mi = 2 * li - i;
            if (i >= ti || m[mi] + i >= ti) {
                left = i;
                right = i;
                while (left > 0 && right < nn-1 && access(s, left-1) == access(s, right+1)) {
                    left --;
                    right ++;
                }
                li = i;
                ti = right;
                m[i] = (right - left + 2) / 2;
            } else m[i] = _min(ti - i, m[mi]);
        }
        return m;
    }
    int isPalindrome(int* m, int minIndex, int maxIndex) {
        return m[(maxIndex + minIndex + 1)] > maxIndex - minIndex + 1;
    }
    int minCut(string s) {
        int sn = s.size();
        int ans = 0;
        int* m = manacher(s, sn);
        int* rec = new int[sn];
        for (int i = 0; i < sn; i ++) {
            if (isPalindrome(m, 0, i)) {
                rec[i] = 0;
                continue;
            }
            rec[i] = INT_MAX - 1;
            for (int j = 1; j <= i; j ++) {
                if (isPalindrome(m, j, i)) {
                    rec[i] = _min(rec[i], rec[j-1] + 1);
                }
            }
        }
        delete(m);
        ans = rec[sn-1];
        delete(rec);
        return ans;
    };
};

void swap(int* a, int *b ) {
    int t = *a;
    *a = *b;
    *b = t;

}

void swap2(int& a, int &b) {
    int t = a;
    a = b;
    b = t;
}

int main() {
    string s = "cadfdsdfefbvabadfafsbcbc";
    cout<<Solution1().minCut(s)<<endl;;
    cout<<Solution2().minCut(s)<<endl;;
    return 0;
}


Python Solution: github

#coding=utf-8

'''
    url: leetcode.com/problems/palindrome-partitioning-ii
    @author:     zxwtry
    @email:      zxwtry@qq.com
    @date:       2017年5月15日
    @details:    Solution:  792ms 29.31%
'''

class Solution(object):
    def index(self, s, i):
        return "#" if i % 2 == 0 else s[i // 2]
    
    def manacher(self, s, sn):
        nn = 2 * sn + 1
        m = [0] * nn
        ti = 0
        mi = 0
        ci = 0
        for i in range(nn):
            mi = 2 * ci - i
            if i >= ti or m[mi] == ti-i:
                li = i
                ri = i
                while li-1 > -1 and ri+1 < nn and \
                    self.index(s, li-1) == self.index(s, ri+1):
                    li, ri = li-1, ri+1
                ti = ri
                ci = i
                m[i] = (ri-li) // 2
            else: m[i] = min(m[mi], ti-i)    
        return m
    
    def isP(self, m, i, j):
        return m[i+j+1] > abs(i-j)
        
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        sn = 0 if s == None else len(s)
        if sn < 1: return 0
        m = self.manacher(s, sn)
        s = [1 << 30] * sn
        for i in range(sn):
            if (self.isP(m, i, 0)): s[i] = 0
            else:
                for j in range(i):
                    if (not self.isP(m, i, j+1)):
                        continue
                    s[i] = min(s[i], s[j]+1)
        return s[sn-1]
        
if __name__ == "__main__":
    s = "abbab"
    print(Solution().minCut(s))





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值