#include <string>
#include <unordered_map>
#include <vector>
#include <iostream>
using namespace std;
/*
Given a string S and a string T, find the minimum window in S which will contain all the
characters in T in complexity O(n).
For example:
S = "ADOBECODEBANC"
T = "ABC"
minumum window is "BANC".
If there is no such window in S that convers all characters in T, return the empty string "".
*/
string minWindow(string s, string t) {
int minLen = s.size()+1;
int minBegin = 0;
int tSize = t.size();
vector<int> count(256, 0);
vector<int> needed(256, 0);
for(int i = 0; i < tSize; ++i) {
needed[t[i]]++;
}
int tCount = 0;
for(int begin = 0, end = 0; end < s.size(); ++end) {
char tmp = s[end];
if(!needed[tmp]) continue;
/* find the longest length that contains all the t chars.*/
if(++count[tmp] <= needed[tmp]) {
tCount++;
}
/* shrink the range to find the shortest one.*/
if(tCount == tSize) {
/* think about this case "AAAABC"*/
while(needed[s[begin]] == 0 || count[s[begin]] > needed[s[begin]]) {
if(count[s[begin]] > needed[s[begin]]) {count[s[begin]]--;};
begin++;
}
int length = end - begin + 1;
if(length < minLen) {
minLen = length;
minBegin = begin;
}
}
}
return minLen > s.size() ? "" : s.substr(minBegin, minLen);
}
int main(void) {
cout << minWindow("ADOBECODEBANC", "ABC") << endl;
}
Facebook asked a simplified version.
#include "header.h"
using namespace std;
string minWindowSubstring(string str, unordered_set<char> chars) {
unordered_map<char, int> charToCount;
int windowSize = str.size() + 1, minStart = 0;
int count = 0;
for(int start = 0, end = 0; end < str.size(); ++end) {
char ch = str[end];
if(chars.find(ch) == chars.end()) continue;
if(charToCount[ch] == 0) {count++; charToCount[ch] = 1;}
else charToCount[ch]++;
if(count == chars.size()) {
cout << "count size : " << count << " "<< "charToCount.size() : " << charToCount.size() << endl; // it is very weird here.
while((chars.find(str[start]) == chars.end()) || (charToCount[str[start]] > 1)) {
if(charToCount[str[start]] > 1) charToCount[str[start]]--;
start++;
}
int size = end - start + 1;
if(windowSize > size) {
windowSize = size;
minStart = start;
}
}
}
return windowSize > str.size() ? "" : str.substr(minStart, windowSize);
}
int main(void) {
unordered_set<char> inputs{'a', 'b', 'c'};
cout << minWindowSubstring("adabbcbbabc", inputs) << endl;
}