最短摘要生成

转自 http://blog.csdn.net/bertzhang/article/details/7278728

题目:抽象点说,就是在一个字符串中,找一些目标字符串,找到包含所有目标字符串的最小字符串。题目虽然叫做最短摘要生成,但和实际的搜索snippet的计算还是有比较大的差距的。

解法:文献[1]给出了一种比较好的解法,策略还是使用双指针,双指针对于很多算法设计很有价值,算法的思想是采用两个指针,开始两个指针都指向缓冲区的头部,尾指针向后扫描,直到头指针和尾指针中间包含了全部的关键字,那么头指针向后移动,直到包含全部关键字这个条件失败,这时截取字串并和已取得的最小字串比较,如果小则替换。头指针、尾指针都向后一个位置(这点很重要,开始就忘记了移动头指针,导致程序出错),继续扫描。另外,由于一个关键字可能重复多次,因此在判断是否包含全部关键字时要采用计数机制,才能保证查看的准确。这样只要头指针和尾指针扫描两次字符串就可以完成生成算法。

#include <stdio.h>
#include <string>
#include <map>
class KeyWordChecker {
 public:
  KeyWordChecker() : current_state_(false) {}
  void AddKeyWord(const std::string& word) {
    if (keywords_.find(word) == keywords_.end()) {      
      keywords_[word] = 0;
    }
  }
  bool IsContainAllKeyWord(const std::string& word, bool add) {
    if (keywords_.find(word) == keywords_.end()) {
      return current_state_;
    }
    if (add) {
      keywords_[word]++;
    } else {
      keywords_[word]--;
    }
    std::map<std::string, int>::iterator begin = keywords_.begin();
    int counter = 0;
    while (begin != keywords_.end()) {
      if (begin->second > 0) {
        counter++;
      } else {
        break;
      }
      begin++;
    }
    if (counter == keywords_.size()) {
      current_state_ = true;
      return true;
    } else {
      current_state_ = false;
      return false;
    }
  }
 private:
  std::map<std::string, int> keywords_;
  bool current_state_;
};

std::string GenerateSnippet(const std::string& content, KeyWordChecker* keyword_checker) {
  int begin = 0;
  int end = 0;
  std::string snippet;
  int min_length = content.size();
  while (end < content.size()) {
    if (!keyword_checker->IsContainAllKeyWord(std::string(1, content[end]), true)) {
       end++;
       continue;
    }
    while (begin <= end && keyword_checker->IsContainAllKeyWord(std::string(1, content[begin]), false)) {
      begin++;
    }
    if (end - begin + 1 < min_length) {
      snippet = content.substr(begin, end - begin + 1);
      min_length = end - begin + 1;
    }
    end++;
    begin++;
  }  
  return snippet;
}
int main(int argc, char** argv) {
  std::string content = "abbbbbcaaadebmmmmdcfg";
  KeyWordChecker keyword_checker;
  keyword_checker.AddKeyWord("b");
  keyword_checker.AddKeyWord("d");
  std::string snippet = GenerateSnippet(content, &keyword_checker);
  printf("snippet:%s\n", snippet.c_str());
}

另外一个代码转自 http://hi.baidu.com/leifenglian/item/33fc082a88c49cd0a517b6d3
// MinAbstractGenerate.cpp : 定义控制台应用程序的入口点。
//
/*
最短摘要生成:
有一个字符串数组序列W,一个关键词数组Q,
在W中找出包含所有关键词组Q中元素的最短序列
*/

/*吐血的算法。。。*/

#include "stdafx.h"
#include <iostream>
using namespace std;

//是否包含所有的字符串
bool isAllExisted(char * src[],int start,int end,char *des[],int deslen)
{
    for(int j=0;j<deslen;j++)
    {
        bool isFind=false;
        for(int i=start;i<end;i++)
        {
            if(strstr(src[i],des[j])!=NULL)
            {
                isFind=true;
            }
        }
        if(isFind==false)
        {
            return false;
        }
    }
    return true;
}

//最小摘要生成
void minAbstractGenerate(char * src[],int srclen,char *des[],int deslen)
{
    int min=0;
    int max=0;
    int begin=0;
    int end=0;
    int distance=srclen;

    while(true)
    {
        while(!isAllExisted(src,min,max,des,deslen) && min<=max)
        {
            max++;
        }

        while(isAllExisted(src,min,max,des,deslen))
        {
            if(max-min<distance)
            {
                distance=max-min;
                begin=min;
                end=max;
            }
            min++;
        }
        if(max>=srclen-1)
        {
            break;
        }
    }

    while(begin<end)
    {
        cout<<src[begin++]<<"***";
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    char *src[]={"ab","ef","cd","gh","ij","k","c","ef","t","ij","yz"};
    char *dec[]={"ef","ij"};
    minAbstractGenerate(src,11,dec,2);
    return 0;
}

转自 http://www.cnblogs.com/jack204/archive/2012/09/03/2668667.html

题目:

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

先来看看这些序列:

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

分析

当初看这道题时,看了好了几遍都没看懂。后来总算弄明白:给出的字符串是用其它程序分好词的,关键字符串也是用其它程序分好词的,而不是按用户直接输入的字符串。比如书上给的例子:“微软亚洲研究院 使命”,不是按空格分成两个关键词,“微软亚洲研究院”和“使命”,而是按其它程序分成:“微软”、“亚洲”、“研究院”和“使命”四个关键词。

“最短摘要”应该是指:包含所有关键字(关键字不要求按用户输入的顺序排列)的长度最短的摘要。书上的解法,把“最短摘要”理解成包含所有关键字且词个数最少的摘要。

 

这个过程要记录最短文摘的信息。
这个时间复杂度是 O(N ^ 2 * M)
N 是文档的长度
M 是关键词数组的大小

总结的滑动窗口法是:

------------------------------------------------------

使用滑动窗口的办法,找出最短摘要。我们把这个滑动窗口叫做摘要滑动窗口
摘要滑动窗口左边界L,右边界R。

窗口中应该维护的信息:

  1.   窗口中已经遍历过的关键字序列----可使用队列才存储;
  2.   窗口中各个关键字出现的个数----可使用hashtable来表示或者数组也行。

[while]

右边界R向右移动的原则:
  当前窗口中不包含所有种类的关键字,R向右移动寻找更新的关键字。

左边界L向右移动的原则:
  当前窗口中已经包含了所有种类的关键字,计算当前摘要长度,并从队列中拿出一个关键字,即L向右移动一个关键字;

L与R一直移动下去,一直到R不能往右移动时候,循环结束。

[end while]


 


 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值