[LeetCode] Shortest Palindrome


Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.

For example:

Given "aacecaaa", return "aaacecaaa".

Given "abcd", return "dcbabcd".

Credits:
Special thanks to @ifanchu for adding this problem and creating all test cases. Thanks to @Freezen for additional test cases.

https://leetcode.com/problems/shortest-palindrome/

其實問題可以轉化成求從s[0]開始的最長回文,找到以s[0]開始的最長回文,將剩下的部分倒序補在字符串前面就是答案。在找以s[0]開始的回文的時候,可以從后向前枚舉回文結束的字符,在第一個找到的地方退出即可。最壞情況下時間復雜度為O(n^2),用C語言提交AC,704ms。

 1 bool isPalindrom(char* s, int start, int end) {
 2     while (start < end) {
 3         if (s[start] != s[end]) return false;
 4         ++start; --end;
 5     }
 6     return true;
 7 }
 8 
 9 char* shortestPalindrome(char* s) {
10     int pos = strlen(s) - 1;
11     for (; pos > 0; --pos) {
12         if (s[pos] == s[0] && isPalindrom(s, 0, pos)) break;
13     }
14     char* res = (char*) malloc(2 * strlen(s) - pos);
15     int idx = 0;
16     for (int i = strlen(s) - 1; i > pos; --i) res[idx++] = s[i];
17     strcpy(res + idx, s);
18     return res;
19 }

但是用C++提交后超時,可能這並不是最佳的答案吧,想到更好的方法后再回來補上代碼(已經想到了,見后文)。

 1 class Solution {
 2 public:
 3     bool isPalindrom(string &s, int start, int end) {
 4         while (start < end) {
 5             if (s[start] != s[end]) return false;
 6             ++start; --end;
 7         }
 8         return true;
 9     }
10     string shortestPalindrome(string s) {
11         int pos = s.length() - 1;
12         if (pos == 0) return s;
13         for (; pos > 0; --pos) {
14             if (s[pos] == s[0] && isPalindrom(s, 0, pos)) break;
15         }
16         string res;
17         for (int i = s.length() - 1; i > pos; --i) res.push_back(s[i]);
18         res += s;
19         return res;
20     }
21 };

 

求最長回文的Manacher算法時間復雜度為O(n),可以用在這里,但是在判斷最長回文的時候需要加一個條件,就是只比較那些以s[0]開始的回文,而根據Manacher算法的特性,id == p[id]時回文一定是從s[0]開始的。所以下面也是用C++寫可以AC的代碼,因為時間復雜度是O(n),所以只用了16ms。關於Manacher算法,可以看我另一篇文章:

http://www.cnblogs.com/easonliu/p/4454213.html

 1 class Solution {
 2 public:
 3     int longestPalindrom(string s) {
 4         string s1;
 5         s1.resize(2 * s.length() + 2);
 6         int idx = 0;
 7         s1[idx++] = '$';
 8         s1[idx++] = '#';
 9         for (char a : s) {
10             s1[idx++] = a;
11             s1[idx++] = '#';
12         }
13         vector<int> p(s1.length(), 0);
14         int res = 0;
15         for (int id = 0, i = 1; i < s1.length(); ++i) {
16             if (i < id + p[id]) p[i] = min(p[2 * id - i], id + p[id] - i);
17             else p[i] = 1;
18             while (s1[i + p[i]] == s1[i - p[i]]) ++p[i];
19             if (id + p[id] < i + p[i]) id = i;
20             if (p[i] == i) res = max(res, i);
21         }
22         return res - 1;
23     }
24     
25     string shortestPalindrome(string s) {
26         int pos = longestPalindrom(s);
27         string res;
28         for (int i = s.length() - 1; i >= pos; --i) res.push_back(s[i]);
29         return res + s;
30     }
31 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM