zoukankan      html  css  js  c++  java
  • 19最短摘要问题

        问题描述:给定一段产品的英文描述,包含N个英文字母,每个英文单词以空格分隔,无其他标点符号;再给定M个英文单词关键字,请说明思路并编程实现方法extractSummary,目标是找出此产品描述中包含M个关键字(每个关键词至少出现一次)的长度最短的子串,作为产品简介输出。 

     

        编程之美有最短摘要生成的问题,与此问题类似。下面介绍这种方法。首先,可以在百度或谷歌中搜索本博客名称的前4个字结构之法,便会在第一个搜索结果中看到:程序员面试、算法研究、编程艺术、红黑树4大经典原创系列集锦与总结作者:July--结构之法算法之道blog之博主。时间:201010-20116月。出处:http://...“

        这段文字就是摘要。那么,这段摘要是怎么产生的呢?可以对问题进行如下的简化。

        1:假设给定的已经是经过网页分词之后的结果,词语序列数组为W。其中W[0], W[1],…, W[N]为一些已经分好的词语。

        2:假设用户输入的搜索关键词为数组Q。其中Q[0], Q[1],…, Q[M]为所有输入的搜索关键词。

        这样,生成的最短摘要实际上就是一串相互联系的分词序列。比如从W[i]到W[j],其中,0<i<j<=N。

     

    思路一:

        在分析问题之前,先看下下面这个W-Q序列:w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

        如上W-Q序列中,我们可以把,q0,w4,w5,q1作为摘要,q0,w9,q1的也可以作为摘要,同样都包括了所有的关键词q0,q1,那么选取哪个是最短摘要呢?答案很明显,后一个更短,选取q0,w9,q1的作为最短摘要,这便是最短摘要的生成。

        由此,我们可以得出解决此问题的思路,如下:

        1:从W数组的第一个位置开始查找出一段包含所有关键词数组Q的序列,从w0开始,一直到w6。计算当前的最短长度,并更新Seq数组。 

        2:对目标数组W进行遍历,从第二个位置w1开始,重新查找包含所有关键词数组Q的序列,同样计算出其最短长度,以及更新包含所有关键词的序列Seq,然后求出最短距离。

        3:依次操作下去,一直到遍历至目标数组W的最后一个位置为止。

        最终,通过比较,咱们确定如下分词序列作为最短摘要。这个算法的时间复杂度为:O(N^2 * M)。

     

    思路二:

        我们试着降低此问题的复杂度。因为上述思路一再进行查找的时候,总是重复地循环,效率不高。那么怎么简化呢?先来看看这些序列:

    w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

        问题在于,扫描肯定是无法避免的,但是如何把两次扫描的结果联系起来呢?这是一个值得考虑的问题。

        沿用前面的扫描方法,再来看看。第一次扫描的时候,假设需要包含所有的关键词,从第一个位置w0处将扫描到w6处:

    w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

        那么,下次扫描应该怎么办呢?先把第一个被扫描的位置挪到q0处后的一格:w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

        这样包含的序列中将减少了关键词q0。那么,我们便可以把第二个扫描位置往后移,这样就可以找到下一个包含所有关键词的序列。即从w4扫描到w9处,便包含了q1,q0:w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

        这样,问题就和第一次扫描时碰到的情况一样了。依次扫描下去,在w中找出所有包含q的序列,并且找出其中的最小值,就可得到最终的结果。编程之美上给出了如下参考代码:

    int  nTargetLen = N + 1;           // 设置目标长度为总长度+1 

    int  pBegin = 0;                     // 初始指针 

    int  pEnd = 0;                       // 结束指针 

    int  nLen = N;                       // 目标数组的长度为N 

    int  nAbstractBegin = 0;           // 目标摘要的起始地址 

    int  nAbstractEnd = 0;           // 目标摘要的结束地址 

     

    while(true) 

        // 假设未包含所有的关键词,并且后面的指针没有越界,往后移动指针 

        while(!isAllExisted() && pEnd <nLen) 

        { 

            pEnd++; 

        } 

         

        // 假设找到一段包含所有关键词信息的字符串 

        while(isAllExisted()) 

        { 

            if(pEnd – pBegin < nTargetLen) 

            { 

                nTargetLen = pEnd – pBegin; 

                nAbstractBegin = pBegin; 

                nAbstractEnd = pEnd – 1;  

            } 

            pBegin++; 

        } 

        if(pEnd >= N) 

            Break; 

     

    (http://blog.csdn.net/v_july_v/article/details/6890054)

     

  • 相关阅读:
    洛谷 P3128 [ USACO15DEC ] 最大流Max Flow —— 树上差分
    洛谷 P3953 [ NOIP 2017 ] 逛公园 —— 最短路DP
    bzoj 3231 [ Sdoi 2008 ] 递归数列 —— 矩阵乘法
    bzoj 1024 [ SCOI 2009 ] 生日快乐 —— 递归
    hdu 5823 color II —— 子集DP
    bzoj 1093 [ ZJOI 2007 ] 最大半连通子图 —— 拓扑+DP
    洛谷 P3959 NOIP2017 宝藏 —— 状压搜索
    最短路(模板
    线段树 扫描线
    Dijkstra算法
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247168.html
Copyright © 2011-2022 走看看