程式設計之美之最短摘要生成

fangjian1204發表於2014-08-15

書上給出了最短摘要的描述即演算法,簡單來說就是:

掃描過程始終保持一個[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上一次出現的位置的下一個位置,每次向後移動一個字元,如果pos[i]>start,則更新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。只要返回第一個即可。



相關文章