书上给出了最短摘要的描述即算法,简单来说就是:
扫描过程始终保持一个[pBegin,pEnd]的range,初始化确保[pBegin,pEnd]的range里包含所有关键字 。然后每次迭代,尝试调整pBegin和pEnd:
1.pBegin递增,直到range无法包含所有关键字
2.pEnd递增,直到range重新包含所有关键字
计算新的range,与旧的range相比,看是否缩短了,如果是,则更新 不考虑关键字的先后顺序 。这里给出最短摘要算法的几个应用,首先是leetcode上面的两题:
Minimum Window Substring
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"
Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T, return the emtpy string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
思路:和最短摘要类似,只是编程之美中没有给出具体的实现。这里使用了两个数组,一个是摘要的字符的个数,一个是当前找到的摘要的个数。当找到
完整的摘要时,就开始移动窗口左端的指针,算法和编程之美中的一样
class Solution { public: string minWindow(string S, string T) { int needChar[256] = {0},findChar[256] = {0},i,sLen = S.size(),tLen = T.size(); for(i = 0; i < tLen; ++i) ++needChar[T[i]]; int begin = 0 , end = 0 , minWindowSize = INT_MAX , windowLeft = 0,windowRight = 0 , count = 0; for(; end < sLen ;++end ) { if(needChar[S[end]] == 0)continue; if(++findChar[S[end]] <= needChar[S[end]])++count; if(count == tLen)//找到一个完整的摘要 { while(begin <= end) { if(needChar[S[begin]] == 0) { ++begin; continue; } if(findChar[S[begin]] > needChar[S[begin]])//尽可能的移动窗口的左指针 { --findChar[S[begin++]]; continue; } else break;//此时,左窗口指针已不能移动 } if(end - begin + 1 < minWindowSize)//更新当前窗口的大小 { minWindowSize = end - begin + 1; windowLeft = begin; } } } if(minWindowSize == INT_MAX)return ""; return S.substr(windowLeft,minWindowSize); } };
Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring
is "b", with the length of 1.
思路:start指向当前不存在重复的字符的开始位置,pos[i]表示字符i的最大位置,每次向后移动一个字符,如果存在重复字符,则更新start
class Solution { public: int lengthOfLongestSubstring(string s) { int start = 0 , end = 0 , maxLength = 0; int pos[256] = {0}; for(;end < s.size();++end) { if(pos[s[end]] > start)start = pos[s[end]];//即s[end]在前面已经出现错,为了没有重复,start指向上次s[end]出现的下一个位置 if(end - start + 1 > maxLength)maxLength = end - start + 1; pos[s[end]] = end + 1;//记录s[end]出现的下一个位置 } return maxLength; } };
笔试题:
1、阿里巴巴2011年
给定一段产品的英文描述,包含M个英文字母,每个英文单词以空格分隔,无其他标点符号;再给定N个英文单词关键字,请说明思路并编程实现方法String extractSummary(String description,String[] key words),目标是找出此产品描述中包含N个关键字(每个关键词至少出现一次)的长度最短的子串,作为产品简介输出。(不限编程语言)20分。
2、人人面试题
求包含所有query的最短距离
一篇文章,切完词之后放到一个vector<string>中,一个查询切完词也放到一个vector<string>中,写一个函数找出这篇文章中包含这个查询中所有词的最小区间的i和j。只要返回第一个即可。
编程之美之最短摘要生成