class Solution:
def shortestPalindrome(self, s: str) -> str:
rev = s[::-1]
for i in range(len(s) + 1):
if s.startswith(rev[i:]):
return rev[:i] + s
class Solution {
public:
string shortestPalindrome(string s) {
string rev = s;
reverse(rev.begin(), rev.end());
for (int i = 0; i <= s.size(); ++i) {
if (s.substr(0, s.size() - i) == rev.substr(i)) {
return rev.substr(0, i) + s;
}
}
return "";
}
};
class Solution {
public String shortestPalindrome(String s) {
String rev = new StringBuilder(s).reverse().toString();
for (int i = 0; i <= s.length(); i++) {
if (s.startsWith(rev.substring(i))) {
return rev.substring(0, i) + s;
}
}
return "";
}
}
var shortestPalindrome = function(s) {
let rev = s.split('').reverse().join('');
for (let i = 0; i <= s.length; i++) {
if (s.startsWith(rev.slice(i))) {
return rev.slice(0, i) + s;
}
}
return "";
};
Given a string s
, you are asked to find and return the shortest palindrome you can form by adding characters in front of s
. In other words, you may add as many characters as you want to the beginning of s
so that the resulting string is a palindrome (reads the same forwards and backwards), but you cannot add characters elsewhere.
You must return one valid solution. The solution should be as short as possible. The input string s
can be empty or contain only lowercase English letters.
The naive way to solve this problem is to try to make the string a palindrome by checking, for every possible prefix, if the string becomes a palindrome when that prefix is mirrored in front. This would mean, for each possible split, checking if the prefix is a palindrome and, if not, adding the minimal necessary characters.
However, this brute-force approach is inefficient, especially for longer strings. We want to optimize our solution by focusing on the longest palindromic prefix of s
. If we can find the longest prefix of s
that is itself a palindrome, then the minimal set of characters to add is simply the reverse of the remaining suffix, placed in front of s
.
So, the challenge becomes: how do we efficiently find the longest palindromic prefix?
s
to get rev
.
i
(from 0 up to the length of s
), check if the original string s
starts with the substring rev[i:]
. In other words, see if the suffix of the reversed string matches the prefix of s
.
i
where this is true indicates that the prefix s[0:len(s)-i]
is a palindrome. The minimal characters to add are rev[0:i]
(the unmatched part of the reversed string).
rev[0:i] + s
as the shortest palindrome.
This method ensures that we are always adding the minimal number of characters in front, and leverages string matching to avoid unnecessary checks.
For even faster solutions, advanced algorithms like KMP (Knuth-Morris-Pratt) can be used to find the longest palindromic prefix in linear time, but the above method is simple and efficient enough for most practical cases.
Let's take the input s = "aacecaaa"
.
rev = "aaacecaa"
s
starts with rev[0:] = "aaacecaa"
→ Nos
starts with rev[1:] = "aacecaa"
→ Yess
starts with rev[1:]
, the unmatched part is rev[0:1] = "a"
"a" + "aacecaaa" = "aaacecaaa"
The process stops at i = 1
, and we prepend "a"
to form the shortest palindrome.
With advanced string matching algorithms (like KMP), the time complexity can be improved to O(N), but the presented solution is simple and suffices for most cases.
The key insight is to find the longest palindromic prefix of the input string. By reversing the string and checking for the largest overlap, we can efficiently determine the minimal set of characters to prepend. This approach avoids unnecessary brute-force checks and leverages string operations to yield a concise and elegant solution.