在字符串集上找到输入的字谜..?

时间:2012-01-23 12:34:20

标签: algorithm map trie

给定一组字符串(大集合)和输入字符串,您需要有效地找到输入字符串的所有字符。您将使用什么数据结构。使用它,你将如何找到字谜?

我想到的是这些:

  1. 使用地图

    a)删除所有字母多于/少于输入的字母。

    b)将输入字符放在地图

    c)遍历每个字符串的地图,看看是否所有字母都带有计数。

  2. 使用尝试

    a)将所有具有正确字符数的字符串放入trie。

    b)遍历每个分支,如果输入中包含字母,则更深入。

    c)如果叶子到达这个词是anagram

  3. 有人能找到更好的解决方案吗?

    您在上述方法中是否有任何问题?

3 个答案:

答案 0 :(得分:5)

从每个单词构建频率图并比较这些地图。

伪代码:

class Word

  string word
  map<char, int> frequency

  Word(string w)
    word = w
    for char in word
      int count = frequency.get(char)
      if count == null
        count = 0
      count++
      frequency.put(char, count)

  boolean is_anagram_of(that)
    return this.frequency == that.frequency 

答案 1 :(得分:4)

您可以构建一个哈希映射,其中键被排序(单词),值是一个列表,列出了所有单词,排序,给出相应的键:

private Map<String, List<String>> anagrams = new HashMap<String, List<String>>();

void buildIndex(){
    for(String word : words){
        String sortedWord = sortWord(word);
        if(!anagrams.containsKey(sortedWord)){
            anagrams.put(sortedWord, new ArrayList<String>());
        }
        anagrams.get(sortedWord).add(word);
    }
}

然后,您只需查找刚刚构建的hashmap中的已排序单词,您将获得所有字谜的列表。

答案 2 :(得分:0)

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/*
 *Program for Find Anagrams from Given A string of Arrays.
 *
 *Program's Maximum Time Complexity is O(n) + O(klogk), here k is the length of word.
 *
 * By removal of Sorting, Program's Complexity is O(n) 
 *  **/
public class FindAnagramsOptimized {
    public static void main(String[] args) {
        String[] words = { "gOd", "doG", "doll", "llod", "lold", "life", 
"sandesh", "101", "011", "110" };
        System.out.println(getAnaGram(words));
    }
    // Space Complexity O(n)
    // Time Complexity O(nLogn)
    static Set<String> getAnaGram(String[] allWords) {
        // Internal Data Structure for Keeping the Values
        class OriginalOccurence {
            int occurence;
            int index;
        }
        Map<String, OriginalOccurence> mapOfOccurence = new HashMap<>();
        int count = 0;
        // Loop Time Complexity is O(n)
    // Space Complexity O(K+2K), here K is unique words after sorting on a

    for (String word : allWords) {
        String key = sortedWord(word);

        if (key == null) {
            continue;
        }
        if (!mapOfOccurence.containsKey(key)) {
            OriginalOccurence original = new OriginalOccurence();
            original.index = count;
            original.occurence = 1;
            mapOfOccurence.put(key, original);
        } else {
            OriginalOccurence tempVar = mapOfOccurence.get(key);
            tempVar.occurence += 1;
            mapOfOccurence.put(key, tempVar);
        }
        count++;
    }

    Set<String> finalAnagrams = new HashSet<>();

    // Loop works in O(K), here K is unique words after sorting on
    // characters
    for (Map.Entry<String, OriginalOccurence> anaGramedWordList : mapOfOccurence.entrySet()) {
        if (anaGramedWordList.getValue().occurence > 1) {
            finalAnagrams.add(allWords[anaGramedWordList.getValue().index]);
        }
    }

    return finalAnagrams;
}

// Array Sort works in O(nLogn)
// Customized Sorting for only chracter's works in O(n) time.
private static String sortedWord(String word) {

    // int[] asciiArray = new int[word.length()];
    int[] asciiArrayOf26 = new int[26];
    // char[] lowerCaseCharacterArray = new char[word.length()];
    // int characterSequence = 0;
    // Ignore Case Logic written in lower level
    for (char character : word.toCharArray()) {
        if (character >= 97 && character <= 122) {
            // asciiArray[characterSequence] = character;
            if (asciiArrayOf26[character - 97] != 0) {
                asciiArrayOf26[character - 97] += 1;
            } else {
                asciiArrayOf26[character - 97] = 1;
            }
        } else if (character >= 65 && character <= 90) {
            // asciiArray[characterSequence] = character + 32;
            if (asciiArrayOf26[character + 32 - 97] != 0) {
                asciiArrayOf26[character + 32 - 97] += 1;
            } else {
                asciiArrayOf26[character + 32 - 97] = 1;
            }
        } else {
            return null;
        }

        // lowerCaseCharacterArray[characterSequence] = (char)
        // asciiArray[characterSequence];
        // characterSequence++;
    }
    // Arrays.sort(lowerCaseCharacterArray);

    StringBuilder sortedWord = new StringBuilder();
    int asciiToIndex = 0;
    // This Logic uses for reading the occurrences from array and copying
    // back into the character array
    for (int asciiValueOfCharacter : asciiArrayOf26) {
        if (asciiValueOfCharacter != 0) {
            if (asciiValueOfCharacter == 1) {
                sortedWord.append((char) (asciiToIndex + 97));
            } else {
                for (int i = 0; i < asciiValueOfCharacter; i++) {
                    sortedWord.append((char) (asciiToIndex + 97));
                }
            }
        }
        asciiToIndex++;
    }
    // return new String(lowerCaseCharacterArray);
    return sortedWord.toString();
}
}