Palindrome Pairs

链接:https://leetcode.com/problems...

这道题没想出来思路,参考了这个博客的内容:
http://bookshadow.com/weblog/...

把一个单词分为两个部分:left, right。right部分是回文的,在words里面找是否有reverse的left。这里的left范围是(0, len(word)),最小是0,因为要保证是两个单词,最大是len(word),这时候要找出另一个和他相反的串。根据题目的意思,一个单词只能用一次,而且words里面单词都是unqiue的。
现在的问题就在于如果判断right是否为回文,以及如何找到left的reverse串。判断right为回文,可以直接暴力,每个right都判断一次。找left可以用trie tree或者hashmap。可能出现ab, ccba这种第二个数比一个数长的情况,所以不光要从左到右看,还要从右往左看。两个方向都找一遍就可能出现重复的情况,注意避免重复。

两个词形成的string一样不算重复,只有当两个词的组合重复时才算重复。例如: ["", "aa"],结果应该是[(0,1), (1,0)]。那么什么时候可能出现重复呢?["ab", "ba"],这种两个单词形成了palindrome,如果在ab和ba的两边都查一遍肯定会重复。可以看出规律是当map里面有其中一个词的reverse时,就少算一边即可。

public class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        Map<String, Integer> map = new HashMap();
        for(int i = 0; i < words.length; i++) {
            map.put(new StringBuilder(words[i]).reverse().toString(), i);
        }
        
        List<List<Integer>> result = new ArrayList();
        for(int i = 0; i < words.length; i++) {
            String cur = words[i];
            int n = cur.length();
            for(int j = 0; j <= n; j++) {
                // left: (0, j), right: (j, n)
                // right is palindrome and find reversed left
                String left = cur.substring(0, j);
                String right = cur.substring(j, n);
                if(isPalindrome(right) && map.containsKey(left) && map.get(left) != i) {
                    result.add(Arrays.asList(i, map.get(left)));
                }
                
                // left is palindrome and find reversed right
                if(isPalindrome(left) && map.containsKey(right) && map.get(right) != i) {
                    // avoid duplication
                    if(j == 0 && map.containsKey(cur) && map.get(cur) != i) continue;
                    
                    result.add(Arrays.asList(map.get(right), i));
                }
                
            }
           
        }
        return result;
    }
    
    private boolean isPalindrome(String s) {
        int i = 0, j = s.length() - 1;
        while(i < j) {
            if(s.charAt(i) != s.charAt(j)) return false;
            i++; j--;
        }
        return true;
    }
}

这个博客还用了一种set的方法:
http://www.cnblogs.com/grandy...

暂时还没看懂,明天再看下。。

Shortest Palindrome

题目链接:https://leetcode.com/problems...

这道题和“ Longest Palindromic Substring ” 是一个意思,不同的是这个palindrome string必须要从index = 0开始。最简单的方法就是一个一个试。超时了。。。

Manacher's Algorithm

这个算法是用来找最长回文字串的,利用的是回文的对称信息或者说是prefix信息。

public class Solution {
    public String longestPalindrome(String s) {
        // base case 
        if(s == null || s.length() <= 1)  return s;
        // Manacher Algorithm
        /* new index: 0 1 2 3 4 5 6 
           old index: # 0 # 1 # 2 #
                        m   c   i r
        */
        // An array to store the max length at each center
        int n = s.length() * 2 + 1;
        int[] pivot = new int[n];
        pivotInitial(pivot, s);

        // find the maximum length
        int maxLen = 0;
        int center = 0;
        for(int i = 0; i < n; i++) {
            if(pivot[i] > maxLen) {
                maxLen = pivot[i];
                center = i;
            }
        }
        int lo = (center - maxLen) / 2;
        int hi = lo + maxLen;
        return s.substring(lo, hi);
    }

    // Manacher 
    /* new index: 0 1 2 3 4 5 6 
       old index: # 0 # 1 # 2 #
                  m   c   i r
    */
    private void pivotInitial(int[] arr, String s) {
        // center and maximum reachable index
        int c = 0, r = 0;
        for(int i = 0; i < arr.length; i++) {
            int diff = r - i;
            // mirror to i with pivot c
            int m = c - (i - c);
            // the maximum palindrome is in the reachable
            if(diff >= 0 && arr[m] < diff) {
                arr[i] = arr[m];
            }
            else {
                // if i > r, then just start from i
                int left = i / 2 - 1;
                int right = i / 2 + i % 2;
                // start from the index that exceed the reachable index
                if(diff >= 0) {
                    left -= diff / 2;
                    right += diff / 2;
                }
                // update center and maximum reachable
                arr[i] = len(s, left, right);
                c = i;
                r = i + arr[i];
            }
        }
    }

    private int len(String s, int left, int right) {
        while(left >= 0 && right <= s.length() - 1) {
            if(s.charAt(left) == s.charAt(right)) {
                left--;  right++;
            }
            else break;
        }
        return right - left - 1;
    }
    
}

KMP

这个算法是用来找substring的,利用的是substring自身的prefix信息。

// KMP algorithm

public class KMPSubstringSearch {

    /* compute the prefix array for the pattern string */
    private int[] prefixArray(String pattern) {
        int[] pre = new int[pattern.length()];
        // pre[0] = 0, pre[i] means the index of prefix
        // index used to store the position of matched prefix
        int index = 0;
        int i = 1;
        while(i < pattern.length()) {
            if(pattern.charAt(i) == pattern.charAt(index)) {
                pre[i] = index + 1;
                i++;  index++;
            }
            else {
                if(index == 0) {
                    pre[i] = 0;
                    i++;
                }
                else {
                    index = pre[index-1];
                }
            }
        }
        return pre;
    }

    // kmp, pattern match, return the position 
    // if no match, return -1
    private int kmp(String text, String pattern) {
        int[] pre = prefixArray(pattern);
        int i = 0; int j = 0;
        char[] ctext = text.toCharArray();
        char[] cpattern = pattern.toCharArray();
        while(i < ctext.length && j < cpattern.length) {
            // match
            if(ctext[i] == cpattern[j]) {
                i++;  j++;
            }
            // not match
            else {
                // first char of the pattern string
                if(j == 0) {
                    i++;
                }
                else {
                    j = pre[j-1];
                }
            }
        }
        if(j == cpattern.length) {
            return i-j;
        }
        else return -1;
    }

    public static void main(String args[]) {
        String text = "abdacabc";
        String pattern = "abc";
        KMPSubstringSearch test = new KMPSubstringSearch();
        int result = test.kmp(text, pattern);
        System.out.println(result);
    }
}

lulouch13
13 声望6 粉丝