LeetCode214. 最短回文串

1.问题描述

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例 1:
输入: “aacecaaa”
输出: “aaacecaaa”
示例 2:
输入: “abcd”
输出: “dcbabcd”

2.问题分析

我们拿aacd这个例子
答案是dcaacd
构建最短回文串我们可以构建一个反过来的s即r_s与s去匹配
s=“aacd”;r_s=“dcaa”
我们假设二者相加,中间加一个标记符来区分两个字符串
新s=“aacd#dcaa”
我们发现,通过求他们的最长公共前后缀就能求最短回文串
最长公共前后缀为2即"aa"
所以就想到了用KMP算法中求prefix_table的想法来求最长公共前后缀
最后再叠加起(r_s除去最长公共前后缀剩下一部分)和(最初的s)即为最短回文串
即"dc"+“aacd”
注意:我们的#的作用不仅仅是分割,当我们输入的字符是aabba那么你会发现按照上面的想法会出现一个bug,那就是当不加#时正序加倒叙为aabbaabbaa最后一个字符的的next数组值为6,比自己的长度还大,后续的处理和其他种类的字符串处理不同,所以#还可以使所有字符串求得next数组值之后的后续处理方式相同

3.代码实现

class Solution {
public:
    string shortestPalindrome(string s){
        if(s.length()==0)
        return "";
        if(s.length()==1)
        return s;
        string  str0=s;
        reverse(str0.begin(),str0.end());
        if(s==str0)
        return s;
        string str1=s;
        string str2=s;
        string str3=s;
        reverse(str1.begin(),str1.end());
        s=s+"#"+str1;
        int kmp[s.length()];
        kmp[0] = 0;
        int t;
        for(int i = 1; i < s.length(); i++)
       {
	     t = kmp[i-1];
	     while(t > 0 && s[i] != s[t])
		 t = kmp[t-1];
	     if(s[i] == s[t])
         {
		  t++;
	      kmp[i] = t;
         }  
           else
           kmp[i]=0;
       } 
       if(kmp[s.length()-1]<=str2.length()-1)
       {
           return str1.substr(0,str1.length()-kmp[s.length()-1])+str3;
       }
       else
       return "";
    }
};

你可能感兴趣的:(算法错题总结)