【LeetCode笔记】Longest Palindromic Substring

Three ways of finding the longest palindromi substring:

1.DP

2.Manacher's 

These two algorithm are analyzed thoroughly in articles linked below:

http://leetcode.com/2011/11/longest-palindromic-substring-part-i.html

http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 

3.Search twice

This one is common and simple

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

My implementation:

1.DP solution: O(N2) time and O(N2) space (could be improved to use O(N) space)

string palindrome_DP(string s){
	int maxStart = 0;  //the smallest i among dp[i][j]s == true
    <span style="white-space:pre">	</span>int maxLen = 1;	   //maxLen = j - i + 1, is the max length among dp[i][j]s == true
	int n = s.size();
	vector<vector<bool> > dp(n, vector<bool>(n, false)); //dp[i][j]: s[i..j] is a palindrome or not
	
	for(int i = n - 1; i >= 0; --i)
        for(int j = i; j < n; ++j)
            if(s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1])){  
            /*this equals (s[i] == s[j] && j - i < 2 || s[i] == s[j] && dp[i + 1][j - 1])
              s[i] == s[j] && j - i < 2 is to check: when j == i, then s[i] == s[j], then dp[i][i] = true;
              				     when j == i + 1, if s[i] == s[i+1] then dp[i][i] = true, else false
              s[i] == s[j] && dp[i + 1][j - 1] is the dp method
             Notice that, s[i] == s[j] && j - i < 2 must be the first condition, or it'll cause memory read problem
            */
				dp[i][j] = true;
				if(j - i + 1 > maxLen){
					maxStart = i;           
					maxLen = j - i + 1;						
				}

            }
	return s.substr(maxStart, maxLen);		
}



2. Manacher’s algorithm: to find the longest palindrome substring in O(N) time and space

<pre name="code" class="cpp">//Manacher's algorithm: O(N) time and O(N) space
string preprocessString(string s){
	string t("#");
	for(int i = 0; i < s.size(); ++i){	
		t += s[i];
		t += "#";		
	}
		return t;
}

string finder(string s){
	vector<int> p(s.size(), 1);
	int mx = 0, id = 0, len = 0, center = 0;
	for(int i = 0; i < s.size(); ++i){
		if(mx > i)
			p[i] = min(p[2 * id - i], mx - i);	
		//expand the panlindrome from the center				
		while (i - p[i] >= 0 && i + p[i] < s.size() && s[i - p[i]] == s[i + p[i]])
			p[i]++;
		//update info of reached panlindrome
		if(i + p[i] > mx){
			mx = i + p[i]; 
			id = i;   
		}
		
		//record the info of the longest palindrome
		if(p[i] - 1 > len){
			len = p[i] - 1;  //len: the length of longest palindrome
			center = i;      //center: the center of the longest palindrome
		}
	}
	//generate the longest palindrome
	string t;  
	for(int i = len; i > 0; --i)
		t += s[center + p[center] - 2 * i];	
	return t;	
}

string palindrome_Manacher(string s){
	s = preprocessString(s);
	s = finder(s);
	return s;<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

Time analysis: in the for loop, comparison begins at mx, and mx increases linearly, and elements between the old mx and the new mx wont be compared, so is O(N) method.

 

3.a simple solution: O(N2) time and O(1) spacego over the string twice to find the odd palindrome and even palindrome

string palindrome_Twice(string s){
	int n = s.size();
	if(n <= 1)
		return s;
	//n >= 2
	int maxLen = 1;
	int maxStart = 0;
	for(int i = 1; i < n; ++i){
		//find the longest even palindrome around i
		int low = i - 1;
		int high = i;
		while(low >= 0 && high < n && s[low] == s[high]){
			if(high - low + 1 > maxLen){
				maxLen = high - low + 1;
				maxStart = low;
			}
			low--;
			high++;			
		}
		//find the longest odd palindrome around i
		low = i - 1;
		high = i + 1;
		while(low >= 0 && high < n && s[low] == s[high]){
			if(high - low + 1 > maxLen){
				maxLen = high - low + 1;
				maxStart = low;
			}
			low--;
			high++;			
		}
	}
	return s.substr(maxStart, maxLen);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值