2013-08-17 42 views
3

我需要一些幫助來解決這個問題。計算句子中兩個詞的同現(java)

我有一個字符串的兩次脫節列表: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 

你有什麼建議嗎?謝謝!

回答

1

您有2個列表。對於列表中的每個單詞,從第一個單詞到列表中其餘單詞的映射。例如,如果你在此列表中有 「人工智能」, 「蝙蝠洞」, 「狗」,你會保存它作爲:

"artificial" => { "artificial intelligence" }

"bat" => { "bat cave" }

"dog" => { "dog" }

這將是第一步。對列表進行預處理,以獲取第一首的地圖到列表中剩餘的單詞。

現在當你的行包含像「人工智能很酷」的聲明。你用\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 

有很多的優化做的。

+0

非常感謝:) – Epi

1

我不確定我是否完全理解了您的要求,但如果您只需要計數,就可以給列表中的字符串加權。例如,如果你有項

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

如果句子中包含「人工智能」,這三個將匹配給權重的總和= 1

這將需要一些預處理來計算正確的權重爲字符串。

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 
} 

希望我理解你的問題

0

我想我找到了一個解決方案,你幫我想着它。

我可以做的是分別迭代這兩個列表,並在兩個臨時地圖中添加我在句子中找到的單詞(用權重來計算出現的次數)。之後,我可以總是分開迭代這兩個映射,如果一個字符串a1包含一個字符串a2,我將a2的權重遞減一。之後,我將獲得2張包含正確權重的地圖,並且我可以迭代它們以遞增每個對的同現。

我認爲這種方式它應該工作!

+0

你還在接受建議嗎?我準備好了一個實現。 – bsd

+0

肯定爲什麼不能感謝:) – Epi

相關問題