数据结构--Manacher算法(最长回文子串)--生成最短回文串

在给定字符串末尾添加一个字符串,生成回文串,且回文串长度最短

 

可以求字符串包含到最右边的字符的最右回文右边界的中心,然后以此中心为基准,回文半径在左边不包含的部分加上即可
* 2111123 --> 2111123211112
* 32112 --> 321123
* 3211233 --> 321123321123

即求得是包含最后一个字符在内的最长回文直径。

注意:在最后末尾添加字符串时,要记得是将字符串反向添加进去。

延伸到的最右边的那个字符的回文半径flags[center] (即为以center为中心的原字符串的回文直径。)

str.length() - flags[center] + 1就是需要补充的字符串长度

 

public class Manacher_ShortestEnd {
    public static String shortestEnd(String str){
        if(str == null || str.length() == 0) return str;
        char[] ch = new char[str.length() * 2 + 1];
        int index = 0;
        for(int i = 0; i < ch.length; i++){
            ch[i] = (i & 1) == 0 ? '#' : str.charAt( index++ );
        }

        int[] flags = new int[ch.length];
        int maxRight = 0;
        int center = 0;

        for(int i = 0; i < ch.length; i++){
            flags[i] = maxRight > i ? Math.min(flags[2 * center - i], maxRight - i) : 1;
            while(i - flags[i] >= 0 && i + flags[i] < ch.length){
                if(ch[i - flags[i]] == ch[i + flags[i]]){
                    flags[i]++;
                }
                else break;
            }
            if(i + flags[i] > maxRight){
                maxRight = i + flags[i];
                center = i;
                if(maxRight == ch.length - 1){
                    break;
                }
            }
        }
        char[] res = new char[str.length() - flags[center] + 1];
        for(int i = 0; i < res.length; i++){
            res[res.length - 1 - i] = ch[i * 2 + 1];
        }
        str = str + String.valueOf( res );
        return str;
    }
    public static void main(String[] args){
        String str = "32111233";
        System.out.println(shortestEnd( str ));
    }

}

  

posted @ 2018-05-03 09:49  SkyeAngel  阅读(261)  评论(0编辑  收藏  举报