LeetCode 214. Shortest Palindrome

题意为,允许在字符串的头部添加字符,使其成为回文。最简单的方法是讲该字符串翻转为s2, s2 + s1即为回文,但题目要求的是最短的回文串。


于是问题便转换为一个,求以原字符串首字符开头(s[0])的最长子串的长度(亦即使得s.substr(0, length)为回文的最大length值)这么一个子问题。

       —— 可以想象,当求得这么一个length后,我们将s.substr(length)翻转添加到s头部即为所求(亦即s.substr(length).reverse() + s即为所求)

这个子问题可暴力求解O(N^2)的复杂度,也可以用下述的Manacher算法在O(N)时间内求解。


Manacher算法实现了在O(N)时间内求字符串的最长回文子串(LeetCode 5. Longest Palindromic Substring)

在了解了该算法后,要求以原字符串首字符开头(s[0])的最长子串的长度,只要添加约束p[i] == i, 表示以i为中心回文串,其一边的长度为p[i]. 

若p[i] == i, 那么从i往前推p[i]个位置,那就是原点 —— 所以这是一个包含原字符串s首字母s[0]的回文子串。

通过Manacher算法,求满足p[i] == i的最大i值即可。


代码:

class Solution 
{
public:
    string shortestPalindrome(string s) 
    {
    	string str(2*s.size()+1, 0);
    	for (size_t i = 1; i < str.size(); i += 2)
    	{
    		str[i] = s[i>>1];
    	}
    	vector<int> p(2*s.size()+1, 0);
    	int id=0, mx=0;
    	for (int i = 1; i < str.size(); ++ i)
    	{
    		p[i] = mx>i? min(p[2*id-i], mx-i): 0;
    		for (; i-p[i]-1>=0 && i+p[i]+1<str.size() 
    			&& str[i-p[i]-1]==str[i+p[i]+1]; ++ p[i]) {}
    		if (i + p[i] > mx)
    		{
    			mx = i + p[i];
    			id = i;
    		}
    	}

    	int max_length = 0;
    	for (int i = 1; i < str.size(); ++ i)
    	{
    		max_length = i==p[i]? i: max_length;
    	}
    	string non_palindrome_postfix = s.substr(max_length);
    	reverse(non_palindrome_postfix.begin(), non_palindrome_postfix.end());
    	return non_palindrome_postfix + s;
    }
};



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值