使用Java(在Android上)我试图找到一种方法(快速...)来解决这个问题:
我有一个单词列表(大约10到30个)和一个文档。文档的长度也可以变化,可能大约2500到10000字。本文档是一本书的一部分。
我想要的是在本文档中找到包含列表中较高数量单词的字符串(句子...)。文档中的单词必须与我的单词列表顺序相同。通常情况下,文档中的单词不应该是另一个,也可能是我列表中每个单词之间最多2或3个单词。
为了更清楚,让我们以小数据为例。
我的单词列表是:
伤害工作日
我的文件:
就是这样,非常小心。你必须确保你拉起来 定期所有的猴面包树,在他们可以的第一时刻 区别于他们非常接近的玫瑰丛 他们最早的年轻人。这是一项非常繁琐的工作,“小王子 补充说,“但很容易。”有一天他对我说:“你应该 做一个漂亮的画,让你住的孩子都可以看到 究竟是怎么回事。如果他们这对他们非常有用 有一天会去旅行。有时,“他补充说,”没有伤害 推迟工作的 直到另一个日。但 当它是猴面包树的问题时,这总是意味着灾难。一世 我知道一个懒惰的人居住的星球。他忽略了三个 小灌木......“所以,正如小王子向我描述的那样,我 画了那个星球。我不太喜欢拿 道德主义者的语气。但猴面包树的危险性很小 理解,任何人都会冒这样的风险 可能会迷失在一颗小行星上,一旦我突破了我的星球 保留。 “孩子们,”我坦率地说,“小心猴面包树!”
目标是在文档中找到字符串“在推迟工作之前没有任何损害”。
目前,我想到的唯一方法是:
1 - 在文档的列表中找到第一个出现的第一个单词。
2 - 将列表中的单词数乘以2或3,得到我必须在文档中检查的字符串长度(关于文档中列表单词之间的最大单词数)。
3 - 通过拆分和循环搜索此文档字符串(具有在步骤2中获得的字符串长度)的列表中其他单词的出现。
如果我认为我在这个字符串中出现的单词不够(可能大约50%),那么继续搜索文档,从下一次出现的列表中的第一个单词开始。
但是我担心这可能会很长很长,特别是因为我正在使用移动设备...所以我来这里是为了抓住一些我可能没想过的想法,或者一些可以帮助我完成这项任务的libs。我也考虑过正则表达式,但我不确定它是不是更好的方式。
@gukoff命题
最后,我的单词列表与我的文本的顺序不同,它简化了算法。 @gukoff答案的开头就足够了。无需实施LIS算法或反转列表。
//Section = input text
//wordsToFind = words to find in text separated by space
private ArrayList<ArrayList<Integer>> test1(String wordsToFind, Section section) {
//1. Create the index of your words array.
String[] wordsArray = wordsToFind.split(" ");
ArrayList<Integer> indexesSentences = new ArrayList<>();
ArrayList<ArrayList<Integer>> sentenceArrayIndexes = new ArrayList<>();
ArrayList<Integer> wordsToFindIndexes = new ArrayList<>();
for(Sentence sentence:section.getSentences()) {
indexesSentences.clear();
for(String sentenceWord:sentence.getWords()) {
wordsToFindIndexes.clear();
int j = 0;
for(String word:wordsArray) {
if(word.equals(sentenceWord)) {
wordsToFindIndexes.add(j+1);
}
j++;
}
//Collections.reverse(wordsToFindIndexes);
for(int idx:wordsToFindIndexes) {
indexesSentences.add(idx);
}
}
sentenceArrayIndexes.add((ArrayList<Integer>)indexesSentences.clone());
}
return sentenceArrayIndexes;
}
public class Section {
private ArrayList<Sentence> sentences;
public Section (String text) {
sentences = new ArrayList<>();
if(text == null || text.trim() == "") {
throw new IllegalArgumentException("Text not valid");
}
String formattedText = text.trim().replaceAll("[^a-zA-Z. ]", "").toLowerCase();
String[] sentencesArray = formattedText.split("\\.");
for(String sentenceStr:sentencesArray) {
if(sentenceStr.trim() != "") {
sentences.add(new Sentence(sentenceStr));
}
}
}
public ArrayList<Sentence> getSentences() {
return sentences;
}
public void addSentence(Sentence sentence) {
sentences.add(sentence);
}
}
答案 0 :(得分:1)
这是一个简单的方法,根据您的文档大小应该足够好:
array
(称之为words
),其大小为n
,其中n
是您document
中的字数。现在填充此数组,以便
words[i] = 0
如果list
中没有任何字词与此字词匹配
words[i] = k
如果kth
中的list
字符与此字词匹配(1
为基础的索引),则there is no harm in putting off a piece of work until another day.
示例:如果您的文档为work day harm piece
且字词列表为words
(按此顺序),那么您的[0,0,0,3,0,0,0,0,4,0,1,0,0,2]
数组将如下所示2000~3000
2.现在您将拥有一个整数 //AS Rev
var elementsasrev = $(this).parent().find('tr').filter('.'+trclass);
var asrev = parseInt(elementsasrev.eq(1).find("td:nth-child(6)").html());
if(typeof asrev !== "undefined") {
$('.'+trclass).not(this).find(".asrev").html(asrev);
}
//FBspend
var fbspend = parseInt($(this).find("td:nth-child(7)").html() );
$(this).find(".fbspend").html(fbspend);
//Profit
var profit= asrev - fbspend;
$(this).find(".profit").html(profit).css('color','#479e3a');
的数组。您可以使用Longest common subsequence problem的变体或稍微修改您的算法以找到最佳匹配。
答案 1 :(得分:1)
因此,您可以找到要找到的单词和一个由要检查的句子组成的文本。
例如,如果words
= a dog is not a human
:
{
"a": [1, 5],
"dog": [2],
"is": [3],
"not": [4],
"human": [6]
}
"a"
被[5, 1]
取代,"human"
被[6]
取代,"tree"
被[]
取代。例如,句子"not a cat is a human"
应变为[4, 5,1, 3, 5,1, 6]
例如,[4, 5,1, 3, 5,1, 6]
的LIS为[1, 3, 5, 6]
,其映射到子匹配"a is a human"
。
但一般来说,如果这些词语不应该相距很远,我建议使用动态编程找到LIS并进行相应的修改。