给定两个字符串 s 和 t 。返回 s 中包含 t 的所有字符的最短子字符串。如果 s 中不存在符合条件的子字符串,则返回空字符串 “” 。
如果 s 中存在多个符合条件的子字符串,返回任意一个。
注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最短子字符串 "BANC" 包含了字符串 t 的所有字符 'A'、'B'、'C'
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入:s = "a", t = "aa"
输出:""
解释:t 中两个字符 'a' 均应包含在 s 的子串中,因此没有符合条件的子字符串,返回空字符串。
提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
class Solution {
public:
string minWindow(string s, string t) {
int n1=s.size(),n2=t.size();
string ans;
if(n1<n2)
return ans;
int ct1[130]={0},ct2[130]={0},ct3[130]={0};
int oks=0;
for(int i=0;i<n2;++i)
{
if(ct2[t[i]]==0) ++oks; //统计有几类字符
++ct2[t[i]];
}
int l=0,r=0,ok=0,i;
int flag=1,minN=100010,temp,pos;
char tc;
while(r<n1&&l<=r)
{
tc=s[r];
++ct1[tc];
if(ct2[tc]&&!ct3[tc]&&ct1[tc]==ct2[tc]) //对t中存在的字符进行比较,若相等则ok数+1
{
++ok;
ct3[tc]=1; //重复则不计数
}
if(ok==oks)
{
if(!flag)
flag=1;
tc=s[l];
while(ct1[tc]>ct2[tc]&&l<=r) //找到s和t第一个相等个数字符的位置
{
--ct1[tc];
++l;
tc=s[l];
}
temp=r-l+1;
if(temp<minN) //更新长度
{
minN=temp;
pos=l;
}
--ct1[tc];
--ok;
ct3[tc]=0;
++l; //计数少1,清除重复标记,左指针向右移动
}
++r; //右指针移动,滑动窗口向右扩展
}
if(flag) //存在结果则更新ans
ans=s.substr(pos,minN);
return ans;
}
};