leetcode214. Shortest Palindrome构造最短回文串

问题:给定一个字符串str,只允许在首部添加字符,求构造的最短回文串的长度。

思路:找到以str[n-1]为结尾的最长回文串,设为str[i,n-1];再用前半部分的翻转链接到该串即可:reserve(str[0,i-1])+str

实现:若str[i,n-1]是以str[n-1]为结尾的最长回文串,则反转str后,有reserve(str)[0,n-i-1] equals str[i,n-1],于是转化为reserve(str)+str的最长公共前后缀问题。为避免前后缀越界,用两个不同的特殊字符标记。

class Solution {
    public String shortestPalindrome(String s) {
        if(s.length()==0){
        	return s;
        }
        StringBuilder sb=new StringBuilder(s);
        sb.append('#');//加一个标识防止s+reverse(s)得到的最长公共前后缀长度超过原串
        sb.append(new StringBuilder(s).reverse().toString());
        sb.append('!');//在最后任意加一个字符(遵循kmp的next数组的语义,求目标最长公共前后缀),不与标志字符‘#’相同即可。
        return new StringBuilder(s.substring(getNext(sb.toString())[sb.length()-1])).reverse().append(s).toString();
    }
    /**
     * kmp算法.通过模式串得失配next数组--‘next[i],在i位置发生失配’,pattern[0,i-1]的最长公共前后缀'长度',又下一个字符的索引值==长度
     * next[i],pattern[0,i-1]的最长公共前后缀的长度。notice:length((前缀|后缀))<=length(str)-1,即前缀后缀的概念不含字符串本身
     */
    private int[] getNext(String pattern){
    	int[] next=new int[pattern.length()];
    	next[0]=-1;
    	int pre;//待验证字符索引,关键变量
    	for(int i=1;i<pattern.length();i++){
    		pre=next[i-1];
    		while(pre!=-1 && pattern.charAt(i-1)!=pattern.charAt(pre)){//比较pattern[i-1]与pattern[pre]
    			pre=next[pre];//kmp核心
    		}
    		if(pre==-1){
    			next[i]=0;
    		}else{
    			next[i]=pre+1;
    		}
    	}
    	return next;
    }
}
变种:若只能从尾部加字符,则转化为求str+reserve(str)的最长公共前后缀


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值