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.
先来个直接的,就是求出从字符串起始处开始的最长回文串,如果有这样的回文串存在(必然存在,单个字符就是一个回文串,但找到的回文串长度越长,补全后的回文串整体长度就越小),我们只需要以这个找到的回文串为中心,再在字符串前补全即可。但是TLE
class Solution { public: string shortestPalindrome(string s) { int len = s.size(); int idx; for (idx=len; idx>0; idx--) { if (isPar(s, 0, idx)) { break; } } string mirror; for (int i=len - 1; i>=idx; i--) { mirror.push_back(s[i]); } return mirror + s; } bool isPar(string& s, int start, int end) { int p = start; int q = end - 1; while (p < q) { if (s[p] != s[q]) { return false; } p++, q--; } return true; } };
一样的思路,别人的就简洁很多 ,92ms
class Solution { public: string shortestPalindrome(string s) { string s2=s; reverse(s2.begin(),s2.end()); int n=s.size(),l; for(l=n;l>=0;l--) { if(s.substr(0,l)==s2.substr(n-l)) break; } return s2.substr(0,n-l)+s; } };
还是一样的思路,但是加入高效求回文串的过程(manacher's algorithm,见另一篇自己博客图解,网上资料也很多),时间8ms,速度提高太多了
class Solution { public: string shortestPalindrome(string s) { string ss("$"); for (int i=0; i<s.size(); i++) { ss.push_back(s[i]); ss.push_back('$'); } int len = ss.size(); vector<int> pl(len, 1); int far = 0; int mid = 0; int longest = 0; int mirror = 0; for (int i=0; i<len; i++) { int cfar = i; // if this index is covered by exist palindrome if (far > i) { mirror = 2 * mid - i; cfar = min(pl[mirror], far - i) + cfar; } // spread out while (cfar < len && (2 * i - cfar >= 0) && ss[cfar] == ss[2 * i - cfar]) { cfar++; } // current palindrome single part length(incuded middle character) pl[i] = cfar - i; // update right farest index covered by palindrome if (cfar > far) { mid = i; far = cfar; } // is this palindrome start from s[0]? if (2 * i - cfar == -1) { // index i in ss is just the palindrome length in s(original string) longest = i; } } string str = s.substr(longest); reverse(str.begin(), str.end()); return str + s; } };
discuss里还有用KMP做的,不过KMP不熟,以后再写。
改写一下:
class Solution { public: string shortestPalindrome(string s) { if (s.size() < 2) { return s; } int plen = palindrome(s); string left = s.substr(plen); reverse(left.begin(), left.end()); return left + s; } int palindrome(string& s) { string ms(s.size() * 2 + 1, '$'); int i = 0; for (char ch : s) { ms[i++ * 2 + 1] = ch; } int mlen = ms.size(); vector<int> lens(mlen, 0); int far = 0; int lcenter = 0; int maxlen = 2; for (int i=0; i<mlen; i++) { int p = i, q = i; if (i < far) { int mirror = 2 * lcenter - i; int step = min(lens[mirror], far - i); p -= step; q += step; } while (p >= 0 && q < mlen && ms[p] == ms[q]) { p--, q++; } if (q > far) { far = q; lcenter = i; } lens[i] = q - i; if (p < 0) { maxlen = max(maxlen, lens[i]); } } return (maxlen * 2 - 1) / 2; } };