字符串----最短摘要生成

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

思路一:

直接暴力解法,循环暴力破解,每次判断关键字是否全部包含,然后不断更新边界。

思路二:

先来看看这些序列(w为英文单词,q为关键字):

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

问题在于,一次性扫描确定边界这不太现实,肯定要多次扫描,不断更新边界,这里只说每个关键字必须要出现一次以上,并没有说要顺序出现。先第一次扫描,扫描到第一个关键字,从第一个位置w0处将扫描到q0处:

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

然后扫描的位置继续往后移动,移动到q1,这样包含的序列中就少了q0,那么就从q1开始扫描,这样就可以找到下一个包含所有关键字的序列,即从q1扫描到了q0处,这儿也要更新边界:

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

然后,在继续往后扫描,定位到下一个关键字q0,继续往后扫描,如此循环往后扫描,直至扫描完成,那么边界长度就是最小的了。

代码:

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

public class 最短摘要 {

    public static void main(String[] args) {
         solve1(new String[]{"a", "b", "c", "seed", "h", "e", "f", "c", "c", "seed", "e", "f", "seed", "c"},
                 new String[]{"c", "e"});
         solve2(new String[]{"a", "b", "c", "seed", "c", "e", "f", "c", "c", "seed", "e", "f", "seed", "c"},
                 new String[]{"c", "c", "e", "f"});
         solve2(new String[]{"a", "b", "a", "a", "b", "c", "d", "h", "e", "f", "f"}, new String[]{"b", "c", "d"});
    }

    // 暴力破解法
    public static void solve1(String[] w, String[] q) {
        int length = Integer.MAX_VALUE;
        int begin = -1;
        int end = -1;
        for (int i = 0; i < w.length; i++) {
            // 求以i开头包含所有关键字的序列
            for (int j = i+1; j < w.length; j++) {
                // 如果全部关键字已经再seq中。
                if (containsAll(q,w,i,j)) {
                    // 判断当前这个序列是不是较短的序列
                    // System.out.println(seq);
                    if (j-i+1<length) {
                        length = j-i+1;
                        begin = i;
                        end = j;
                    }
                    break;
                }
            }
        }
        print(w,begin,end);
    }

    /**
     * 这种解法解决了keys关键字中有重复的现象
     * @param w
     * @param keys
     */
    public static void solve2(String[] w, String[] keys) {
        Arrays.sort(keys);
        // begin和end用于在找到更短的包含全部关键字的子数组时更新
        int begin = -1;
        int end = -1;

        int j = -1;  // 上一次囊括了所有关键字的右边界

        int minLen = Integer.MAX_VALUE;
        for (int i = 0; i < w.length; i++) {
            // 如果i位置是关键字,求以i开头包含所有关键字的序列
            String word1 = w[i];
            int index = Arrays.binarySearch(keys, word1);
            if (-1==index) {
                continue;
            }else {  // i是一个关键字
                // 如果已经全部找到
                if (j<w.length&&j>=i&&containsAll(keys, w, i, j)) {
                    if (j-i+1<minLen) {  // 更新
                        minLen = j-i+1;
                        begin = i;
                        end = j;
                    }
                    continue;
                }
            }

            if (j==-1) {
                j = j+1;   // j值初始化
            }
            while(j<w.length){
                String word2 = w[j];  // 文章单词
                int index1 = Arrays.binarySearch(keys, word2);
                if (-1==index1) {
                    j++;
                    continue;
                }else {  // 找到关键字  这里应该是第一次扫描的包含所有关键字的  然后继续for循环不断更新边界
                    if (containsAll(keys, w, i, j)) { //全部到齐
                        if (j - i + 1 < minLen) {// 更新
                            minLen = j - i + 1;
                            begin = i;
                            end = j;
                        }
                        break;
                    }else {
                        j++;
                    }
                }
            }
        }
        print(w, begin, end);
    }

    private static boolean containsAll(String[] keywords, String[] w, int i, int j) {
        Map<String, Integer> map = new HashMap<>();
        for (int k = 0; k < keywords.length; k++) {
            String key = keywords[k];
            if (map.get(key)==null) {
                map.put(key, 1);
            }else {
                map.put(key, map.get(key)+1);
            }
        }

        Map<String, Integer> map2 = new HashMap<>();
        for (int k = i; k <= j; k++) {
            String key = w[k];
            if (map2.get(key)==null) {
                map2.put(key, 1);
            }else {
                map2.put(key, map2.get(key)+1);
            }
        }
        for(Map.Entry<String, Integer> e:map.entrySet()){
            if (map2.get(e.getKey())==null||map2.get(e.getKey())<e.getValue()) {
                return false;
            }
        }
        return true;
    }

    private static void print(String[] w, int begin, int end) {
        System.out.println(begin+" "+end);
        for (int i = begin; i <=end; i++) {
            System.out.print(w[i]+" ");
        }
        System.out.println();
    }

}

结果:

  

原文地址:https://www.cnblogs.com/xiaoyh/p/10306633.html

时间: 2024-10-30 07:23:20

字符串----最短摘要生成的相关文章

最短摘要生成

题目: Alibaba笔试题:给定一段产品的英文描述,包含M个英文字母,每个英文单词以空格分隔,无其他标点符号: 再给定N个英文单词关键 字,请说明思路并编程实现方法String extractSummary(String description,String[] key words), 目标是找出此产品描述中包含N个关键字(每个关键词至少出现一次)的长度最短的子串,作为产品简介输出.(不限编程语言)20分. 在网上看到一种用链表实现的方法,时间复杂度可以达到O(m+n).在这里实现一下. 分析

编程之美之最短摘要生成

书上给出了最短摘要的描述即算法,简单来说就是: 扫描过程始终保持一个[pBegin,pEnd]的range,初始化确保[pBegin,pEnd]的range里包含所有关键字 .然后每次迭代,尝试调整pBegin和pEnd: 1.pBegin递增,直到range无法包含所有关键字 2.pEnd递增,直到range重新包含所有关键字 计算新的range,与旧的range相比,看是否缩短了,如果是,则更新 不考虑关键字的先后顺序 .这里给出最短摘要算法的几个应用,首先是leetcode上面的两题: M

最短摘要问题

/* 最短摘要问题,给一定字符串序列 wo,w1,w2,w3,op1,w4,op2,w5,op1,w6,w7,op1,op2,指定关键字符串为op1,op2,求包含关键字的最小字符串序列. 常见于搜索引擎的分词,op1,op2这里没有顺序,否则就更复杂了,最短序列为op1,op2. 思路: (1)第一次扫描要包含全部关键词,送wo扫描到op2,即w0,w1,w2,w3,op1,w4,op2,随后左边逐渐缩小,知道第一次不全包含关键字为止(在扫描时候 就记录最短的),即w4,op2.此时移动右面知

编程之美-最短摘要

这个主要注意几点:首先,str[i]-str[j]包含keyword里面的所有词语,但是不要求顺序相同,然后,str[i]-str[j]是所有满足这样要求的最短子串. 主要方法是:deque<index> store: 记录当前摘要的所有单词在str中的下标,map<string, int> record记录所有当前摘要中出现的次数.min_len:当前最短摘要的长度.min_index_first:当前最短摘要的第一个词语在str中的下标,min_index_last:当前最短摘

TensorFlow文本摘要生成 - 基于注意力的序列到序列模型

1 相关背景 维基百科对自动摘要生成的定义是, "使用计算机程序对一段文本进行处理, 生成一段长度被压缩的摘要, 并且这个摘要能保留原始文本的大部分重要信息". 摘要生成算法主要分为抽取型(Extraction-based)和概括型(Abstraction-based)两类. 传统的摘要生成系统大部分都是抽取型的, 这类方法从给定的文章中, 抽取关键的句子或者短语, 并重新拼接成一小段摘要, 而不对原本的内容做创造性的修改. 这类抽取型算法工程上已经有很多开源的解决办法了, 例如Git

【编程之美】3.5 最短摘要的生成

题目:有搜索后的网页分词序列 数组W 其中W[0].W[1]....W[N]为分好的词. 用户输入的关键词为数组 Q 其中Q[0].Q[1]...Q[M]为搜索的关键词. 找到W中最小的范围W[i]~W[j]让其包括所有的Q. 思路: 最想当然的思路就是从W[0]开始,对每个Q遍历判断有没有一样的,截取出第一个包含Q中元素的W[i]到最后一个包括Q中元素的W[j].需要O(MN)次比较. 如果前提能够肯定W中包含所有的Q那就,先从W[0]开始找到第一个包含Q的,再从W[N-1]向前找第一个包含Q

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

题意:假设给定的已经是经过网页分词之后的结果,词语序列数组为W.其中W[0], W[1], ... , W[N]为一些已经分好的词语.假设用户输入的搜索关键词为数组Q.其中Q[0], Q[1], ... Q[m]为所有输入的搜索关键词. 例如,我们可以看到这样一个序列: w0, w1, w2, w3, q0, w4, w5, q1, w6, w7, w8, q0,  w9, q1 解法思路: 第一次扫描时,假设包含所有关键词,将得到如下的结果(用 a 这种形式表示指向位置) w0, w1, w2

3.5 最短摘要的声成

题目: Alibaba笔试题:给定一段产品的英文描述,包含M个英文字母,每个英文单词以空格分隔,无其他标点符号:再给定N个英文单词关键字,请说明思路并编程实现方法String extractSummary(String description,String[] key words),目标是找出此产品描述中包含N个关键字(每个关键词至少出现一次)的长度最短的子串,作为产品简介输出.(不限编程语言)20分 这题跟书上3.5差不多意思的题目. 思路解法: 先来看看这些序列: w0,w1,w2,w3,q

c语言通过空格分割字符串,并生成多个字符串数组

本科学的一点点C语言早就忘光了,偏偏做计算机系统的作业还得用C写,深感C语言的内存分配还有字符串处理太麻烦. 作业需要将程序运行后接收到的字符串(命令)切割成多个字符数组(指令及参数),在网上搜不到,自己写了个(实在不知道c语言本身是否带这个函数,找不到). 因为太弱,不知道该怎么自动分配内存,于是自己设置:指令最多10条,每条指令的长度50. 函数返回一个指向二维字符数组的指针. char **trim(char *cmd) { char **argv; char **rtr; argv =