Algorithm 从包含在O(n)时间内属于给定查询的所有单词的段落中查找最小长度的代码段

Algorithm 从包含在O(n)时间内属于给定查询的所有单词的段落中查找最小长度的代码段,algorithm,Algorithm,给定一个评论段落和关键词,从包含所有关键词的段落中找出最短长度的片段。如果有数以百万计的评论,你会做什么预处理步骤。 第一部分很简单,就是最小窗口问题。现在,对于预处理,我使用倒排索引。因此,每次复习我都会建立一个表来存储每个单词的出现列表。现在,当查询到来时,我检索每个单词的索引列表。现在,有没有办法在O(n)时间内从这组列表中找出最小窗口长度?我尝试构建最小和最大堆来存储每个列表的当前索引,然后跟踪最小窗口长度(使用两个堆的根)。然后我执行extractMin操作,并从max堆中删除相同的元

给定一个评论段落和关键词,从包含所有关键词的段落中找出最短长度的片段。如果有数以百万计的评论,你会做什么预处理步骤。
第一部分很简单,就是最小窗口问题。现在,对于预处理,我使用倒排索引。因此,每次复习我都会建立一个表来存储每个单词的出现列表。现在,当查询到来时,我检索每个单词的索引列表。现在,有没有办法在O(n)时间内从这组列表中找出最小窗口长度?我尝试构建最小和最大堆来存储每个列表的当前索引,然后跟踪最小窗口长度(使用两个堆的根)。然后我执行extractMin操作,并从max堆中删除相同的元素。为了保留max堆中每个元素的位置地址(用于删除),我维护了一个哈希表。现在,从提取的元素所属的列表中,我将下一个元素插入到这两个堆中,并根据需要更改窗口长度。这需要O(nlogn)时间。有可能在O(n)时间内完成吗?

假设此组合已排序,我会这样做:

  • 创建一个描述单词及其索引的对象列表,类似于Obj(字符串名,Int-index)
  • Init包含查询的所有关键字的集合
  • Init窗口的下限,作为列表中第一个元素的索引
  • 浏览列表,更新窗口的上界作为当前对象的索引,更新窗口的下界作为查询中任何单词第一次出现的索引(即,一旦min_window设置为实际单词出现的索引,它将不再更新)并从关键字集中删除相应的单词
  • 当集合为空时,保存结果的下限和上限以及代码段的长度
  • 重复步骤2到5,但这次要使用的列表是从上一个min_窗口定义的元素之后的元素开始的列表,如果代码段的长度比上一个短,则只保留min_窗口和max_窗口(应重复此操作,直到无法再找到给定子列表中的所有引用)
#包括
使用名称空间std;
地图字;
void functionlower(字符串和str){
转换(str.begin(),str.end(),str.begin(),::tolower);
}
字符串比较表(字符串和字符串){
字符串温度;
临时调整大小(str.size());
转换(str.begin()、str.end()、temp.begin()、::tolower);
返回温度;
}
int main(){
int-total_-word;
cin>>总字数;
对于(int i=0;i>str;
功能低下(str);
插入({str,0});
}
cin.ignore();
字符串str;
向量;
getline(cin,str);
int指数=0;

对于(int i=0;i假设字长不变,此解决方案可以在O(n)时间复杂度下实现,其中n是段落中的字数;以下是java实现代码:

package Basic.mins包含所有关键字;
导入java.util.*;
/**
*给出一个评论段落和关键词,
*从包含任意顺序的所有关键字的段落中查找最小长度的代码段。
*/
公共类解决方案{
公共字符串minSnippet(字符串参数,设置关键字){
LinkedList deque=新建LinkedList();
字符串[]单词=段落拆分(\\s”);
for(int i=0;i1){
int first=deque.pollFirst();
int second=deque.peekFirst();
如果(单词[第一个]!=单词[第二个]){
报价第一(第一);
打破
}
}
而(deque.size()>1){
int first=deque.pollLast();
int second=deque.peek last();
如果(单词[第一个]!=单词[第二个]){
最后报价(第一);
打破
}
}
if(deque.isEmpty())
返回“”;
返回字符串。join(“,
copyOfRange(words,deque.peekFirst(),deque.peekLast()+1));
}
/*
例子:
我叫shubham mishra
名字是什么
*/
公共静态void main(字符串[]args){
扫描仪sc=新的扫描仪(System.in);
字符串para=sc.nextLine();
字符串keyLine=sc.nextLine();
Set关键字=新HashSet();
关键词.addAll(Arrays.asList(keyLine.split(\\s));
System.out.println(新解决方案().minSnippet(段落,关键字));
}
}

您可以用以下示例解释您的方法吗?检查是abc def abc xyz def abc,查询字符串是def abc xyz。因此,现在表将是abc-0,2,5 def-1,4 xyz-3。因此,您将从窗口的下限0开始,并将其从集合中删除。现在您遍历集合并将上限更新为1,删除它,再次使上限为3并删除它。因此得到的窗口大小为4(3-0+1)。但所需的窗口大小为3(5-3+1)。请您纠正我。示例在哪里?示例:审阅是abc def abc xyz def abc,查询字符串是def abc xyz。因此,现在表将是abc-0,2,5 def-1,4 xyz-3。因此,您将从窗口的下限0开始,并将其从集合中删除。现在,您遍历集合并将上限更新为1,删除它并删除agAN使上界=3并移除它。因此,窗口大小=4(3-0+1)。但是,需要的窗口大小是3(5-3+1)。好的,当阅读评论时,你可以生成以下列表:L=(ABC,0),(DEF,1),(abc,2),(XYZ,3),(DEF,4),(ABC,5)。现在这个列表是按Word索引排序的。.让我们先设置window\u min=window\u max=0(列表中第一个元素的索引),然后再通过t
#include<bits/stdc++.h>
using namespace std;
map<string,int>word;
void functionlower(string& str){
    transform(str.begin(),str.end(),str.begin(),::tolower);
}
string compareWord(string& str){
    string temp;
    temp.resize(str.size());
    transform(str.begin(),str.end(),temp.begin(),::tolower);
return temp;
}
int main(){
int total_word;
cin>>total_word;
for(int i=0;i<total_word;i++){
    string str;
    cin>>str;
    functionlower(str);
    word.insert({str,0});
}

cin.ignore();
string str;
vector<string>para;
getline(cin,str);
int index=0;
for(int i=0;i<=str.size();i++){
    if(i==str.size()||str[i]==' '){para.push_back(str.substr(index,i-index)); index=i+1;}
}
int currlen=0;
int currpos=0;
int lenprint=0;
int olen=-1;
int opos=-1;
for(int i=0;i<para.size();i++){
    string search=compareWord(para[i]);
    if(word.find(search)!=word.end()){
        if(word[search]==0)currlen++;
        word[search]++;
    }
    while(currlen>=word.size()){
        search=compareWord(para[currpos]);
        if((i-currpos)<olen||olen==-1){
            olen=i-currpos;
            opos=currpos;
        }
        if(word.find(search)!=word.end()){
            if(word[search]==1)break;
            word[search]--;
            currpos++;
            lenprint=i;
        }else currpos++;
    }
}
for(int i=0;i<=olen;i++){
cout<<para[opos+i]<<" ";
}
cout<<endl;
return 0;
}