从Shortest Palindrome谈到Manacher和KMP算法

投出去的三份实习简历都没收到消息...略郁闷...只好闷头刷题了QAQ....

最近按题目类型在重刷Leetcode, 当中做到Shortest Palindrome,开始是用后缀数组做,结果TLE...

只好用马拉车法AC...顺便用KMP算法写了一份AC代码....

后缀数组方法就不说了,可以参考博文后缀数组学习笔记...

马拉车法(Manacher)可以参考博文Manacher算法...下面只贴出Manacher方法AC代码

class Solution{
	int longestPdr(vector<char> & vc){
		vector<int> mana(vc.size(), 0);
		int maxi = -1, maxl = 0, len = 0;
		for (int i = 0; i < vc.size(); ++i){
			if (i > maxi + maxl)
				for (int j = 1; i - j >= 0 && i + j < vc.size() && vc[i - j] == vc[i + j]; mana[i] = j++);
			else if (mana[2 * maxi - i] == maxi + maxl - i)
				for (int j = mana[2 * maxi - i]; i - j >= 0 && i + j < vc.size() && vc[i - j] == vc[i + j]; mana[i] = j++);
			else
				mana[i] = mana[2 * maxi - i];
			if (i + mana[i] > maxi + maxl)
				maxi = i, maxl = mana[i];
		}
		for (int i = 0; i < mana.size(); ++i)	if (mana[i] == i)	len = i;
		return len;
	}
public:
	string shortestPalindrome(string s) {
		vector<char> vc;
		for (int i = 0; i < s.length(); ++i){
			vc.push_back('#');
			vc.push_back(s[i]);
		}
		vc.push_back('#');
		int maxLen = longestPdr(vc);
		string str = s.substr(maxLen);
		for (int i = 0; i < str.length(); ++i){
			s.insert(0, 1, str[i]);
		}
		return s;
	}
};

oK...下面重点说下使用KMP算法...

言语讲不明白...还是贴代码吧...鄙人好懒...

class Solution {
	vector<int> nextArray(string & s){
		vector<int> nextA(s.length(), 0);
		if (s.length() < 3) return nextA;
		int i = 1, j = 1, k = nextA[1];
		while (i < s.length() - 1){
			if (j == 0 || s[i] == s[k]){
				nextA[++i] = (j == 0 ? 0 : nextA[j] + 1);
				j = i;
				k = nextA[j];
			}
			else{
				j = k;
				k = nextA[j];
			}
		}
		return nextA;
	}
	
	int KMP(string Str, string Pat){
		vector<int> nextA = nextArray(Pat);
		int i, j;
		for (i = 0, j = 0; i < Str.length(); ++i){
			if (Str[i] == Pat[j]){
				++j;
			}
			else{
				while (j != 0){
					j = nextA[j];
					if (Str[i] == Pat[j]){
						++j;
						break;
					}
				}
			}
		}
		return j;
	}

public:
	string shortestPalindrome(string s) {
		string rs;
		for (int i = s.length() - 1; i >= 0; --i) rs.push_back(s[i]);
		int len = KMP(rs, s);
		string str = s.substr(len);
		for (int i = 0; i < str.length(); ++i){
			s.insert(0, 1, str[i]);
		}
		return s;
	}
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值