给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
class Solution {
public:
string longestPalindrome(string s) {
//动态规划
if(s.size()<=1)return s;
int pos=0,n=1;
//bool dp[s.size()][s.size()];//不会自动初始化!!!!
vector<vector<bool>> dp(s.size(),vector<bool>(s.size()));
for(int i=0;i<s.size();++i){
dp[i][i]=true;
if(i<s.size()-1&&s[i]==s[i+1]){
dp[i][i+1]=true;
pos=i;
n=2;
}
}
for(int i=2;i<s.size();++i){
for(int j=0;j+i<s.size();++j){
if(s[j]==s[j+i] &&dp[j+1][j+i-1]){
dp[j][j+i]=true;
pos=j;
n=i+1;
}
}
}
return s.substr(pos,n);
}
};
manacher马拉车算法->最长回文子串https://segmentfault.com/a/1190000008484167?utm_source=tag-newest
1 转为为奇回文问题
2 p[i]
表示以 i 为中心的最长回文的半径(p[i] - 1
正好是原字符串中最长回文串的长度)
3 mx 代表以 id 为中心的最长回文的右边界(注意:s[mx]不属于以id为中心的回文字符串),也就是mx = id + p[id]
class Solution {
public:
string longestPalindrome(string s) {
//马拉车算法
string ss="$#",res="";
/*
for(int i=0;i<s.size();++i)
ss=ss+s[i]+'#';//ss+=s[i]+'#'会报错!*/
for(auto &i:s) ss=ss+i+'#';
vector<int> p(ss.size(),1);
int mx=0,id=0;
int maxl=0,maxi;
for(int i=1;i<ss.size();++i){
if(i<mx) p[i]=min(p[(id<<1)-i],mx-i);
while(ss[i-p[i]]==ss[i+p[i]]) ++p[i];//头有'$'尾有'\0'所以不用临界判断
if(p[i]+i>mx){//更新id,mx,注意并不是跟新最大值
id=i;
mx=id+p[id];
}
if(maxl<p[i]){//不是与p[id]比
maxl=p[i];
maxi=i;
}
}
/*if(ss[maxi]!='#')
res+=ss[maxi];
for(int i=1;i<p[maxi];++i)
if(ss[maxi+i]!='#')
res=ss[maxi+i]+res+ss[maxi+i];
return res;*/
return s.substr((maxi-maxl)>>1,maxl-1);
}
}
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
class Solution {
public:
string s,p;//设全局变量和从上层传入&型参数 执行速度差不多
bool isMatch(string s, string p) {
this->s=s;
this->p=p;
//return helper(s,0,p,0);
return helper(0,0);
}
//bool helper(string &s,int is,string &p, int ip){//不加&会超出时间限制
bool helper(int is,int ip){
if(ip>=p.size())return is>=s.size();//这一行和下一行的is<s.size()不好理解
bool a=is<s.size()&&(s[is]==p[ip]||p[ip]=='.');
if(ip+1<p.size()&&p[ip+1]=='*')//当前任意+后一个是*
return helper(is,ip+2)||a&&helper(is+1,ip);
else//当前任意+后一个不是*
return a&&helper(is+1,ip+1);
}
};
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
class Solution {
public:
vector<string> table = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> letterCombinations(string digits) {
if(digits.size()==0)return {};
vector<string> res;
helper(res,"",digits.begin(),digits.end());//多叉树 深度优先遍历
return res;
}
void helper(vector<string> &res,string temp,string::iterator it,string::iterator e){
if(it!=e){
string s=table[*it-'2'];
for(auto &c:s)
helper(res,temp+c,it+1,e);
}
else
res.push_back(temp);
}
};
class Solution {//层序
public:
vector<string> table = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> letterCombinations(string digits) {
if(digits.size()==0)return {};
queue<string> q;
q.push("");
for(auto &i:digits){
string s=table[i-'2'];
int qSize=q.size();
while(qSize--){
for(auto &j:s)
q.push(q.front()+j);
q.pop();
}
}
vector<string>res;
while(q.size()){
res.push_back(q.front());
q.pop();
}
return res;
}
};