编程之美--3.5最短摘要生成

本文介绍了一种用于生成产品描述中最短摘要的算法,该算法能够有效地找出包含所有指定关键词的最短子串。通过使用HashMap和数组来优化字符串比较过程,提高了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

  这道笔试题和编程之美最短摘要生成的方法类似,我用java实现了这个方法。

  先来看看这些序列:

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;  
}   
复制代码

  以下是我写的java实现代码。
     使用HashMap将关键字映射到数字,减少字符串比较,能进一步提高效率。使用数组保存关键字被访问到的次数,用来判断是否包含全部关键字。

复制代码
package com.flyoung;

import java.util.HashMap;
import java.util.Map;

public class Abstract {
/*
 * 编程之美 最短摘要生成
 * */
    
    private int[] keywordsArray; //记录关键字被访问次数的数组
 private int pBegin=0;//查找起始点
 private int pEnd=0;//查找终点
 private int abstractBegin=0;//摘要起始点
 private int abstractEnd=0;//摘要终点
 private int targetLen;//摘要最小长度
 private Map<String,Integer> map;//将关键字映射成数字
 
    public Abstract(String[] keywords){
        int len = keywords.length;
        this.keywordsArray = new int[len];
        this.map = keywordsMap(keywords);
    }
    public String extractSummary(String description,String[] keywords){
        String[] array = description.split(" ");//将字符串转化为数组
 return extract(array,keywords);
    }
    //实际的抽取函数
 public String extract(String[] description,String[] keywords){
        String summary = "";
        int nLen = description.length;
        targetLen = nLen+1;
        while(true){
            while(!isAllExisted()&&pEnd<nLen){
                if(this.map.get(description[pEnd])!=null){
                    setKeywordsArray(keywordsArray,this.map.get(description[pEnd]),0);
                }
                pEnd++;
            }
            while(isAllExisted()){
                if(pEnd-pBegin<targetLen){
                    targetLen = pEnd-pBegin;
                    abstractBegin = pBegin;
                    abstractEnd = pEnd-1;
                }
                if(map.get(description[pBegin])!=null){
                    setKeywordsArray(keywordsArray,map.get(description[pBegin]),1);
                }
                pBegin++;
            }
            if(pEnd>=nLen){
                break;
            }
        }
        for(int j=abstractBegin;j<=abstractEnd;j++){
            if(j!=abstractEnd){
                summary = summary+description[j]+" ";
            }else{
                summary +=description[j];
            }    
        }
        return summary;
    }
    public Map<String,Integer> keywordsMap(String[] keywords){
        Map<String,Integer> map = new HashMap<String,Integer>();
        int len = keywords.length;
        for(int i=0;i<len;i++){
            map.put(keywords[i], i);
        }
        return map;
    }
    //设置关键字被访问到的次数
 public void setKeywordsArray(int[] keywordsArray,int i,int flag){ //flag:0 add flag:1 sub
 if(flag==0){
            keywordsArray[i]++;
        }else{
            keywordsArray[i]--;
        }
    }
    //检查是否包含全部关键字
 public boolean isAllExisted(){
        boolean result = true;
        for(int a:keywordsArray){
            if(a==0){
                result=false;
                break;
            }
        }
        return result;
    }
    
    public static void main(String[] args) {
        String description="hello software hello test world spring sun flower hello";
        String[] keywords = {"hello","world"};
        Abstract nAbstract = new Abstract(keywords);
        System.out.println(nAbstract.extractSummary(description, keywords));
    }
}
D题 天然肠衣搭配问题 天然肠衣(以下简称肠衣)制作加工是我国的一个传统产业,出口量占世界首位。肠衣经过清洗整理后被分割成长度不等的小段(原料),进入组装工序。传统的生产方式依靠人工,边丈量原料长度边心算,将原材料按指定根数和总长度组装出成品(捆)。 原料按长度分档,通常以0.5米为一档,如:3-3.4米按3米计算,3.5-3.9米按3.5米计算,其余的依此类推。表1是几种常见成品 的规格,长度单位为米,∞表示没有上限,但实际长度小于26米。 表1 成品规格表 长度 大长度 根数 总长度 3 6.5 20 89 7 13.5 8 89 14 ∞ 5 89 为了提高生产效率,公司计划改变组装工艺,先丈量所有原料,建立一个原料表。表2为某批次原料描述。 表2 原料描述表 长度 3-3.4 3.5-3.9 4-4.4 4.5-4.9 5-5.4 5.5-5.9 6-6.4 6.5-6.9 根数 43 59 39 41 27 28 34 21 长度 7-7.4 7.5-7.9 8-8.4 8.5-8.9 9-9.4 9.5-9.9 10-10.4 10.5-10.9 根数 24 24 20 25 21 23 21 18 长度 11-11.4 11.5-11.9 12-12.4 12.5-12.9 13-13.4 13.5-13.9 14-14.4 14.5-14.9 根数 31 23 22 59 18 25 35 29 长度 15-15.4 15.5-15.9 16-16.4 16.5-16.9 17-17.4 17.5-17.9 18-18.4 18.5-18.9 根数 30 42 28 42 45 49 50 64 长度 19-19.4 19.5-19.9 20-20.4 20.5-20.9 21-21.4 21.5-21.9 22-22.4 22.5-22.9 根数 52 63 49 35 27 16 12 2 长度 23-23.4 23.5-23.9 24-24.4 24.5-24.9 25-25.4 25.5-25.9 根数 0 6 0 0 0 1 根据以上成品和原料描述,设计一个原料搭配方案,工人根据这个方案“照方抓药”进行生产。 公司对搭配方案有以下具体要求: (1) 对于给定的一批原料,装出的成品捆数越多越好; (2) 对于成品捆数相同的方案,长度长的成品越多,方案越好; (3) 为提高原料使用率,总长度允许有± 0.5米的误差,总根数允许比标准少1根; (4) 某种规格对应原料如果出现剩余,可以降级使用。如长度为14米的原料可以和长度介于7-13.5米的进行捆扎,成品属于7-13.5米的规格; (5) 为了食品保鲜,要求在30分钟内产生方案。 请建立上述问题的数学模型,给出求解方法,并对表1、表2给出的实际数据进行求解,给出搭配方案。给我求解的MATLAB代码
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值