[笔试面试]串s1="ABCDACDAE" s2="DAE" 找出s1中,包含s2的最小子串,要求该子串含有s2中的所有字符,串内字符无顺序关系
思路:首先用一个hash标识s2中出现的所有字符,count记录不重复的字符数,temp_count记录当前已经有的不重复字符数,用left和right指针扫描s1,用另一个hash记录left和right之间每个字符出现的次数。right每前进一步,如果指向的不是s2中的字符,继续前进,如果是s2中的字符,如果是第一次遇见该字符,temp_count加一,如果temp_count等于count则尽量右移left指针,left指针右移有两种情况:1.left指向的字符不在s2中。2.left指向的字符在s2中,且当前出现的次数大于1次。
1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 using namespace std; 5 6 #define MAX 500 7 int map[MAX]; 8 9 int main() 10 { 11 string s1, s2; 12 while(cin>>s1>>s2) 13 { 14 int cnt[MAX]; 15 memset(cnt, 0, sizeof(cnt)); 16 memset(map, 0, sizeof(map)); 17 int i; 18 for(i=0; i<s2.length(); i++) 19 { 20 map[s2[i]] = 1; 21 } 22 int count = 0;//子串中不同字符的数量 23 for (i=0; i<MAX; i++) 24 { 25 if (map[i]) 26 { 27 count++; 28 } 29 } 30 int temp_count = 0; 31 int begin = 0, end = 0; 32 int result_begin = 0, result_end = 0x7fffffff; 33 for(;end<s1.length(); end++) 34 { 35 if (map[s1[end]] == 1)//出现在子串中,否则不感兴趣 36 { 37 cnt[s1[end]]++; 38 if (cnt[s1[end]]==1)//第一次出现该字符 39 { 40 temp_count++; 41 } 42 if (temp_count==count)//每一个字符都已经出现过 43 { 44 while (map[s1[begin]]==0 || (map[s1[begin]]==1 && cnt[s1[begin]]>1))//begin指向的字符不在子串中 或者在begin和end之间begin指向的字符出现好多次 45 { 46 if (map[s1[begin]]) 47 { 48 cnt[s1[begin]]--; 49 } 50 begin++; 51 } 52 if (result_end - result_begin > end-begin) 53 { 54 result_end = end; 55 result_begin = begin; 56 } 57 } 58 } 59 } 60 cout<<result_begin<<" "<<result_end<<endl; 61 } 62 return 0; 63 }