3

我需要一些帮助来解决这个问题。

我有两个不连贯的字符串列表:列表中的list A = {a1, ..., an}一个list B = {b1, ..., bn} 元素可以是“人工”或“智能”之类的简单词,也可以由“人工智能”等更多词组合而成。我还有一个包含很多单词的句子。其中一些在两个列表之一中。

我要做的是计算两个列表中的两个字符串在同一个句子中一起出现的次数。

问题是,如果我在句子中找到一个像人工智能这样的词,那么要考虑的正确词只会是“人工智能”(而不是“人工”或“智能”)

我正在考虑从列表中添加每个单词,包含在句子中,在树集中,然后按长度排序并只取最长的单词,但我认为解决方案不是很好和有效。

目前代码看起来像这样(但它仍然存在我正在谈论的问题)

// iterates on the words from the list A
for (String a: A)
    // if the phrase contains the word
    if (phrase.matches(".*\\b" + a + "\\b.*")
        // iterates on the words from the list B
        for (String b: B)
            // if the phrase contains the word
            if (phrase.matches(".*\\b" + b + "\\b.*")
                // do stuffs

你有什么建议吗?谢谢!

4

4 回答 4

1

我的想法是跟踪考虑过的单词,然后进行清理。

尝试这样的事情:

int counter = 0;
List<String[]> h = new ArrayList<String[]>();
HashSet<String> words = new HashSet<String>();

// iterates on the words from the list A
for (String a: A)
    // if the phrase contains the word
    if (phrase.matches(".*\\b" + a + "\\b.*"))
        // iterates on the words from the list B
        for (String b: B)
            // if the phrase contains the word
            if (phrase.matches(".*\\b" + b + "\\b.*")) {

                h.add(new String[]{a,b});
                words.add(a);
                words.add(b);
            }

// clean up:

// 1. clean words
for (String i:words) {
    // in words, keep only strings that are not contained by others
}

// 2. clean h
for (String[] i :  h) {
    // if i[0] or i[1] are both in words, then
    // increment counter... or whatever you want
}

希望我理解你的问题

于 2013-08-17T18:12:08.013 回答
1

您有 2 个列表。为列表中的每个单词制作从第一个单词到列表中其余单词的映射。例如,如果您在此列表中有“人工智能”、“蝙蝠洞”、“狗”,则将其存储为:

"artificial" => { "artificial intelligence" }

"bat" => { "bat cave" }

"dog" => { "dog" }

这将是第一步。预处理列表以获取 firstword 到列表中其余单词的映射。

现在,当您的行包含诸如“人工智能很酷”之类的声明时。你用 分割线\w。你得到的话。我们遇到的第一个词是“人造的”。我们查看之前获得的两个地图。artificial所以我们在其中一张地图中看到了一个键。我们知道该行中的下一个单词是什么。尽管如此,我们还是想与最长的比赛进行比赛。所以我们比较得到对应的单词列表artificial。并进行最长的子串匹配。我们artificial intelliegence一起寻找,因为我们正在寻找最长的匹配。尽管如此,我们对第二个列表重复该过程。根据哪个更长,我们选择它属于列表 1 还是列表 2。

这是一些示例代码。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class WordSplits {
    public static Map<String, List<String>> first2rest(List<String> wordList) {
        Map<String, List<String>> first2RestWords = new HashMap<String, List<String>>();
        for (String word : wordList) {
            // TODO Make it use Pattern. Sample demo. Get the first word of
            // every string.
            String splits[] = word.split("\\W");
            String firstWord = splits[0];
            List<String> restWords = first2RestWords.get(firstWord);
            if (restWords == null) {
                restWords = new ArrayList<String>();
            }
            restWords.add(word);
            // store the complete pattern nevertheless
            first2RestWords.put(firstWord, restWords);
        }

        return first2RestWords;
    }

    public static Map<String, List<Integer>> longestSubstring(String line,
            List<String> first, List<String> second) {
        Map<String, List<Integer>> occurences = new LinkedHashMap<String, List<Integer>>();
        Map<String, List<String>> first2RestWords = first2rest(first);
        Map<String, List<String>> second2RestWords = first2rest(second);

        Matcher wordMatcher = Pattern.compile("\\w+").matcher(line);
        for (int start = 0; start < line.length() && wordMatcher.find(start);) {

            String word = wordMatcher.group();

            String maxWordFirst = "", maxWordSecond = "";
            if (first2RestWords.containsKey(word)) {
                maxWordFirst = longestMatch(
                        line.substring(wordMatcher.start()),
                        first2RestWords.get(word));
            }
            if (second2RestWords.containsKey(word)) {
                maxWordSecond = longestMatch(
                        line.substring(wordMatcher.start()),
                        second2RestWords.get(word));

            }

            if (maxWordFirst.length() > 0 || maxWordSecond.length() > 0) {
                if (maxWordFirst.equals(maxWordSecond)) {
                    System.out.println("Belongs to both the lists : " + maxWordFirst);
                } else {
                    if (maxWordFirst.length() > maxWordSecond.length()) {
                        System.out.println("Belongs to first list:  " + maxWordFirst);
                    } else if (maxWordSecond.length() > maxWordFirst.length()) {
                        System.out.println("Belongs to second list: " + maxWordSecond);
                    }
                }
            } else {
                System.out.println(word + " does not belong to any list");
            }
            // Take some action
            start = wordMatcher.start() + Math.max(maxWordFirst.length(), maxWordSecond.length()) + 1;
            start = Math.max(wordMatcher.end(), start);
        }

        return occurences;
    }

    public static String longestMatch(String line, List<String> wordList) {
        String maxWord = "";
        // poor way to compare
        for (String word : wordList) {
            if (line.startsWith(word) && word.length() > maxWord.length()) {
                maxWord = word;
            }
        }

        return maxWord;
    }

    public static void main(String[] args) {
        longestSubstring("artificial intelligence is cool. bat.",
                Arrays.asList("dog", "cow", "dog", "artificial intelligence", "bat"),
                Arrays.asList("artificial", "hound", "cool", "bat", "dog hound"));
    }
}

要处理的行是"artificial intelligence is cool. bat."

l1 = `"dog", "cow", "dog", "artificial", "artificial intelligence", "bat"`

l2 = `"intelligence", "hound", "cool", "bat", "dog hound"` 

程序的输出是

Belongs to first list:  artificial intelligence
is does not belong to any list
Belongs to second list: cool
Belongs to both the lists : bat 

有很多优化要做。

于 2013-08-17T19:18:33.707 回答
1

我不确定我是否完全理解你的要求,但如果你只需要计数,你可以给列表中的字符串一个权重。例如,如果您有条目

artificial -> 1
intelligence -> 1
artificial intelligence -> -1

如果句子包含“人工智能”,则所有三个都将匹配,并给出权重之和 = 1。

这将需要一些预处理来计算字符串的正确权重。

于 2013-08-17T17:29:21.563 回答
0

我想我找到了解决方案,你帮助我思考了这个问题。

我可以做的是分别在两个列表上进行迭代,并将我在句子中找到的单词添加到两个临时映射中(具有计算出现次数的权重)。之后,我可以始终分别迭代这两个映射,如果字符串 a1 包含字符串 a2,我将 a2 的权重减一。之后,我将获得 2 个包含正确权重的地图,并且我可以迭代它们以增加每对的共现。

我认为这样应该可以工作!

于 2013-08-17T18:35:15.100 回答