最長公共子串、最長公共子序列、最長迴文子串、最長迴文子序列、迴文子串個數
1、最長公共子串
首先看最長公共子串的解答(暴力演算法、動態規劃、)
從優化到再優化,最長公共子串
2、最長公共子序列(LCS)
3、 leetcode 5 Longest Palindromic Substring 最長迴文串
方法1:藉助最長公共子串問題,將原來的string翻轉,求兩個字串的最長公共子串,但是可能出現的情況是S=”abacdfgdcaba”, S′方法2:暴力演算法
調出所有的子串比較是否是迴文串
方法3: 動態規劃
P(i,j) as
following:P(i,j)={true,false,
==Sjj
)P(i,i)=trueP(i,i+1)=(Sii
==Si+1i+1
)事件複雜度和空間複雜度都是n2
方法4: 自中心擴充套件 沒有動態規劃陣列,時間複雜度仍然是n2,空間複雜度是1
每個字串都有一箇中心,一共有2n-1箇中心。迴文串是偶數的時候,中心在兩個字元之間
馬拉車演算法: 516. Longest Palindromic Subsequence 最長迴文子序列 dp演算法: dp[i][j]指的是i,j之間的最大回文子序列 有:class Solution { public: string longestPalindrome(string s) { //使用第四個方法,自中心擴充套件 int start=0,end=0;//儲存當前最長迴文串的起始和終結位置 for(int i=0;i<s.size();i++) { int len1=expandFromCenter(s,i,i);//以當前字元為中心的迴文串(奇數) int len2=expandFromCenter(s,i,i+1);//以當前和下一個字元的中間為中心的迴文串(偶數) int len=max(len1,len2); if(len>end-start+1)//如果求得的新字串長度是比之前儲存的要長的話 { start=i-(len-1)/2; end=i+len/2; } } return s.substr(start,end-start+1);//注意這個函式的用法,是首地址和字串的長度 } int expandFromCenter(string& s,int left,int right){ while(left>=0&&right<=s.size()&&s[left]==s[right]){//這種書寫方式考慮到奇數和偶數的情況 --left; ++right; } return right-left-1;//返回長度,因為right和left都是移到了迴文串的外圍位置 } };
if i == j, then longest[i][j] = 1, naturally
if i+1 == j, then longest[i][j] = 2 if s[i] == s[j]
longest[i][j] = 1 otherwise
Transition rule:
- s[i] == s[j]
dp[i][j] = max(dp[i+1][j], dp[i][j-1], dp[i+1][j-1] + 2) - s[i] != s[j]
dp[i][j] = max(dp[i+1][j], dp[i][j-1], dp[i+1][j-1])
class Solution {
public:
//lhs means left hand side, rhs means right hand side
int longestPalindromeSubseq(string s) {
if (s.empty()) return 0;
vector<vector<int>> longest(s.size(), vector<int>(s.size()));
for (int len=1; len<=s.size(); len++) {
for (int lhs=0; lhs+len<=s.size(); lhs++) {
int rhs = lhs+len-1;
if (lhs == rhs) {
longest[lhs][rhs] = 1;
} else if (lhs+1 == rhs) {
longest[lhs][rhs] = (s[lhs] == s[rhs]) ? 2 : 1;
} else {
int add = s[lhs] == s[rhs] ? 2 : 0;
longest[lhs][rhs] = max(max(longest[lhs][rhs-1], longest[lhs+1][rhs]), longest[lhs+1][rhs-1] + add);
}
}
}
return longest[0].back();
}
};
另外一種迴圈方式:
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n=s.size();
vector<vector<int>> dp(n,vector<int>(n,0));
for(int i=n-1;i>=0;i--)
{
dp[i][i]=1;
for(int j=i+1;j<n;j++)
{
if(s[i]==s[j])
dp[i][j]=dp[i+1][j-1]+2;
else
dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][n-1];
}
};
647. Palindromic Substrings 統計迴文子串的個數
Given a string, your task is to count how many palindromic substrings in this string.
The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.
Example 1:
Input: "abc" Output: 3 Explanation: Three palindromic strings: "a", "b", "c".
Example 2:
Input: "aaa" Output: 6 Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
Note:
- The input string length won't exceed 1000.
class Solution {
public:
int countSubstrings(string s) {
int sum=0;
int n=s.size();
if(n==0) return 0;
vector<vector<bool>> dp(n,vector<bool>(n,false));
for(int i=n-1;i>=0;i--)
{
dp[i][i]=true;
sum++;
for(int j=i+1;j<n;j++)
{
if(s[i]==s[j])
{
if(i+1==j||dp[i+1][j-1])
{
dp[i][j]=true;
sum++;
}
}
else dp[i][j]=false;
}
}
return sum;
}
};
214. 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"
.
Given two strings s and t, write a function to determine if t is an anagram of s.
For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
Note:
You may assume the string contains only lowercase alphabets.
Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
public:
bool isAnagram(string s, string t) {
vector<int> flag(256,0);
if(s.size()!=t.size()) return false;
for(int i=0;i<s.size();i++)
flag[s[i]]++;
for(int i=0;i<s.size();i++)
{
if(flag[t[i]]==0) return false;
flag[t[i]]--;
}
if(find_if(flag.begin(),flag.end(),com)!=flag.end()) return false;
return true;
}
static bool com(const int s){
return s>0?true:false;
}
};
classSolution {public:boolisAnagram(string s,string t){if (s.length() != t.length()) returnfalse;int n = s.length(); unordered_map<char,int> counts; for (int i = 0; i < n; i++) { counts[s[i]]++; counts[t[i]]--; } for (auto count : counts) if (count.second) returnfalse;returntrue; }};