leetcode 214. Shortest Palindrome (KMP)

Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.

Example 1:

Input: "aacecaaa"
Output: "aaacecaaa"

Example 2:

Input: "abcd"
Output: "dcbabcd"

 

参考别人思路,典型的一道KMP题,想到前缀匹配就应该想到KMP。

KMP本质是一个动态规划,求字符串中以某一下标为结束点时 匹配另一个字符串的最长前缀(可能是两个相同字符串,比如预处理步骤),后面的下标结束点基于前面的匹配结果,快速回退。

字符串P与其翻转后的字符串匹配S。KMP的本质就是字符串P的前缀子字符串 与 某另一个字符串S的后缀的最大匹配。 当一个字符不匹配时,回退到之前的匹配状态。所以要先对P做预处理,用数组dp记录到某个下标时的后缀,匹配之前到某个下标结尾时的前缀。 后面的结果基于前面的结果(回退)。 再匹配S。

P匹配S时也是前缀匹配后缀。但不同情况结束情况也不一样,有时要找到S中是否含有P,所以要完全匹配P,可能在S中某一下标就结束了。 有时,如本题要匹配P最后一个下标结束点 与 S的最长前缀匹配。

此题s对应上面的P,翻转字符串str对应上面的S。网上有把两个字符串连接起来的KMP方法,很巧妙,但把两个字符串分开更接近问题的本质。

class Solution {
    public String shortestPalindrome(String s) {
        int len=s.length();
        if(len==0) return "";
        int[] dp=new int[len];
        dp[0]=-1;
        int cur=-1;
        for(int i=1;i<len;i++){
            dp[i]=-1;
            while(cur!=-1&&s.charAt(i)!=s.charAt(cur+1)){
                cur=dp[cur];//回退到前面的前缀
            }
            if(s.charAt(i)==s.charAt(cur+1)){
                dp[i]=cur+1;
                cur++;    
            }
        }
        String str=new StringBuilder(s).reverse().toString();
        int l=-1;
        for(int i=0;i<len;){
            if(str.charAt(i)==s.charAt(l+1)){
                i++;
                l++;
            }else{
                if(l==-1){//无匹配前缀
                    i++;
                    l=-1;
                }else{
                    l=dp[l];//前一个前缀
                }
            }
        }
        String temp=s.substring(l+1);
        return new StringBuilder(temp).reverse().toString()+s;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值