transient sclass DeepWordIndex { S regexp = "\\w+"; new Map entries; MultiSetMap entriesByWord = ciMultiSetMap(); sclass Entry { A id; Map wordPositions = ciMap(); *(A *id) {} } L wordRanges(S text) { ret regexpFindRanges(regexp, text); } void add(A a, S text) { Entry e = entries.get(a); if (e == null) entries.put(a, new Entry(a)); MultiMap wordPositions = ciMultiMap(); for (IntRange r : wordRanges(text)) { S word = substring(text, r); wordPositions.put(word, r.start); entriesByWord.put(word, e); } for (S word : keys(wordPositions)) e.wordPositions.put(word, toIntArray(wordPositions.get(word))); } }