76. 最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
示例 2:
输入:s = “a”, t = “a”
输出:“a”
示例 3:
输入: s = “a”, t = “aa”
输出: “”
解释: t 中两个字符 ‘a’ 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
char * minWindow(char * s, char * t){
int r[128];//记录t中字母个数
int rt[128];
int i;
for(i=0;i<128;i++){
rt[i]=0;
r[i]=0;
}
i=0;
while(t[i]!='\0'){
r[t[i]-'A']++;
i++;
}
int len=i; //t的长度
int lent=len;
len=len*10;
char ps[len];
int index[len];
int po=0;//ps指针
int posize=0;
int size=0;//已统计的t中有效字母的数量
i=0;
int min =100000,min_index=-1,max_index=-1;
while(s[i]!='\0'){
int index_s=s[i]-'A';
if(r[index_s]!=0){
if(rt[index_s]<r[index_s]){
size++;//有效数据加一
rt[index_s]++;
ps[posize%len]=s[i];//将有效字母放入队列中
index[posize%len]=i;
posize=(posize+1)%len;//长度加一
// printf("si:%d %d ",size,i);
while(size==lent){
// printf("po i index %d %d %d ",po,i,index[po%len]);
int range=i-index[po%len];
if(range<min){
min_index=index[po%len];
max_index=i;
min=range;
}
char ch=ps[po%len];
rt[ch-'A']--;
if( rt[ch-'A']<r[ch-'A']){
size--;
}
po=(po+1)%len;//长度加一
}
}
else{
rt[index_s]++;
ps[posize%len]=s[i];//将有效字母放入队列中
index[posize%len]=i;
posize++;//长度加一
}
}
i++;
}
if(max_index==-1){
s[0]='\0';
return s;
}
s[max_index+1]='\0';
return s+min_index;
}