现在的位置: 首页 > 综合 > 正文

【LeetCode笔记】Longest Palindromic Substring

2018年05月24日 ⁄ 综合 ⁄ 共 2932字 ⁄ 字号 评论关闭

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);
}

抱歉!评论已关闭.