Topic: 187. Repeated DNA sequences
Solution 1: Hash table
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
vector<string> ans;
unordered_map<string, int> mp;
int n=s.size(), L=10;
for(int i=0; i<=n-L; ++i){
//从开头遍历到最后一个长度为10的子串开头
string temp = s.substr(i,L);
if(++mp[temp]==2){
//当数量==2时即可加入答案序列
ans.push_back(temp);
}
}
return ans;
}
};
Solution 2: Hash table + sliding window + bit operation
It’s so long, I don’t want to read it
Topic: 5. The longest palindrome substring
Solution 1: Violent solution
Traverse each substring, and when it is a palindrome substring with the largest length, store the initial position and length.
Time complexity O(n^3), space complexity O(1)
class Solution {
public:
bool isPalindrome(string s, int left, int right){
//判断s字符串中left到right位置的子串是否为回文串
while(left<right){
if(s[left] != s[right]) return false;
++left; --right;
}
return true;
}
string longestPalindrome(string s) {
int n = s.size();
if(n<2) return s; //特判
int maxLen = 1; //最大长度可以是一个字母
int begin = 0; //初始位置
for(int i=0; i<n-1; ++i){
//遍历头,注意遍历到n-1
for(int j=i+1; j<n; ++j){
//遍历从i开始的子串的尾,
if(j-i+1>maxLen && isPalindrome(s, i, j)){
//当子串长度大于当前最大长度,且子串为回文串
maxLen = j-i+1; //更新最大长度
begin = i; //更新起始位置
}
}
}
return s.substr(begin, maxLen); //返回s的最大长度回文子串
}
};
Solution 2: Dynamic programming
It is equivalent to exchanging space for time based on the brute force solution. The time complexity is O(n^2) and the space complexity is O(n). State definition (definition
sub-problem) : Whether a string is a palindrome string after removing the two characters Whether the string is a palindrome string, so the subproblem is defined as: dp[i][j]
Expressed s[i,...,j]
as a palindrome substring
state transition equation (describing the connection between subproblems) : dp[i][j] = (s[i]==s[j]) && (dp[i+1][j-1]=true)
Initialization : The boundary condition is that when the length of the substring is 1, it is obviously a palindrome string. Text substring, for example, i
when j
the characters at the i and j positions of a substring are the same, it is judged whether the length of the substring after removing the i
and j
position characters is a palindrome substring, and it is unanimously judged that the length of the substring after removing i
the and position characters is less than 2 j
, that is -j-1-(i+1)+1<2
> Output j-i<3
: Indicates dp[i][j]
whether i
the j
substring is a palindrome substring, determines whether j-i+1
it is maxLen
greater than Extract the longest palindrome substringmaxLen
begin=i
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
if(n<2) return s; //特判
int maxLen = 1; //最大回文子串长度
int begin = 0; //最大回文子串起始位置
vector<vector<int>> dp(n, vector<int>(n)); //dp定义,true是非0数,false是0
for(int i=0; i<n; ++i){
//初始定义,每个字符单独都是回文子串,对角线为true
dp[i][i] = true;
}
for(int j=1; j<n; ++j){
//从左上角开始遍历,注意从1开始,先遍历列
for(int i=0; i<j; ++i){
//后遍历行,到对角线(j)为止
if(s[i]!=s[j]) dp[i][j]=false; //如果i和j位置的字符不相同,则直接false
else{
//i和j位置字符相同
if(j-i<3){
//边界:j-1-(i+1)+1<2 -> j-i<3
dp[i][j] = true;
}else{
//继续判断i+1到j-1的子串
dp[i][j] = dp[i+1][j-1];
}
}
if(dp[i][j]==true && j-i+1>maxLen){
//检查i到j子串长度是否大于maxLen
maxLen = j-i+1; //更新最大回文子串长度
begin = i; //更新最大回文子串初始位置
}
}
}
return s.substr(begin, maxLen); //截取最长回文子串
}
};
Solution 3: Center expansion method
Time complexity: O(n^2), space complexity: O(1).
Enumerate the number of center positions 2(n-1). Each center spreads to both sides to see if it is a palindrome substring, an even-numbered palindrome substring. and odd palindrome substrings
class Solution {
public:
int ExpandfromCentre(string s, int i, int j){
//从中心开始扩展,检查扩展子串是否是回文子串
int n = s.size();
int left = i, right = j;
while(left>=0 && right<n){
if(s[left]==s[right]){
--left;
++right;
}else{
break;
}
} //不符合i和j位置的字符相同时退出循环,因此返回的回文子串的长度为j-1-(i+1)+1=j-i-1,这里是left和right!!!
return right-left-1;
}
string longestPalindrome(string s) {
int n = s.size();
if(n<2) return s; //特判
int maxLen = 1; //最大回文子串长度
int begin = 0; //最大回文子串起始位置
for(int i=0; i<n-1; ++i){
//枚举中心位置
int oddLen = ExpandfromCentre(s, i, i); //最大奇数回文子串长度
int evenLen = ExpandfromCentre(s, i, i+1); //最大偶数回文子串长度
if(max(oddLen, evenLen) > maxLen){
//更新maxLen和begin
maxLen = max(oddLen, evenLen);
begin = i-(maxLen-1)/2; //注意这里是推导出来的
}
}
return s.substr(begin, maxLen); //截取最长回文子串
}
};
It's a bit troublesome to push begin from i and maxLen. You can choose another way of writing:
class Solution {
public:
pair<int, int> ExpandfromCentre(string s, int i, int j){
//注意函数类型是pair
int n = s.size();
int left = i, right = j;
while(left>=0 && right<n){
if(s[left]==s[right]){
--left;
++right;
}else{
break;
}
} //不符合i和j位置的字符相同时退出循环,因此返回的回文子串的长度为j-1-(i+1)+1=j-i-1,这里是left和right!!!
return {
left+1, right-1}; //注意返回值和{}
}
string longestPalindrome(string s) {
int n = s.size();
if(n<2) return s; //特判
int maxLen = 1; //最大回文子串长度
int begin = 0; //最大回文子串起始位置
for(int i=0; i<n-1; ++i){
auto [odd_l, odd_r] = ExpandfromCentre(s, i, i); //注意加[]
auto [even_l, even_r] = ExpandfromCentre(s, i, i+1);
if(odd_r-odd_l+1 > maxLen){
maxLen = odd_r-odd_l+1;
begin = odd_l;
}
if(even_r-even_l+1 > maxLen){
maxLen = even_r-even_l+1;
begin = even_l;
}
}
return s.substr(begin, maxLen); //截取最长回文子串
}
};