これは、私がしばらく考えていた検索アルゴリズムです。基本的に、アルゴリズムは 2 つのステップで構成されます。
最初のステップでは、y.txt のすべての単語がツリーに挿入されます。ルートからリーフまでのツリー内のすべてのパスは単語です。葉は空です。
たとえば、単語「dog」と「day」のツリーは次のとおりです。
<root>--<d>-<a>-<y>-<>
\-<o>-<g>-<>
アルゴリズムの 2 番目の部分は、ツリーの下方向の検索です。空の葉にたどり着いたとき、単語を見つけたことになります。
Groovy での実装。さらにコメントが必要な場合は、お問い合わせください
//create a tree to store the words in a compact and fast to search way
//each path of the tree from root to an empty leaf is a word
def tree = [:]
new File('y.txt').eachLine{ word->
def t=tree
word.each{ c ->
if(!t[c]){
t[c]=[:]
}
t=t[c]
}
t[0]=0//word terminator (the leaf)
}
println tree//for debug purpose
//search for the words in x.txt
new File('x.txt').eachLine{ str, line->
for(int i=0; i<str.length(); i++){
if(tree[str[i]]){
def t=tree[str[i]]
def res=str[i]
def found=false
for(int j=i+1; j<str.length(); j++){
if(t[str[j]]==null){
if(found){
println "Found $res at line $line, col $i"
res=str[j]
found=false
}
break
}else if(t[str[j]][0]==0){
found=true
res+=str[j]
t=t[str[j]]
continue
}else{
t=t[str[j]]
res+=str[j]
}
found=false
}
if(found) println "Found $res at line $line, col $i"//I know, an ugly repetition, it's for words at the end of a line. I will fix this later
}
}
}
これは私の y.txt です
dog
day
apple
daydream
および x.txt
This is a beautiful day and I'm walking with my dog while eating an apple.
Today it's sunny.
It's a daydream
出力は次のとおりです。
$ groovy search.groovy
[d:[o:[g:[0:0]], a:[y:[0:0, d:[r:[e:[a:[m:[0:0]]]]]]]], a:[p:[p:[l:[e:[0:0]]]]]]
Found day at line 1, col 20
Found dog at line 1, col 48
Found apple at line 1, col 68
Found day at line 2, col 2
Found daydream at line 3, col 7
ツリーの深さは y.txt の単語数に依存しないため、このアルゴリズムは高速です。深さは、y.txt 内の最長の単語の長さと同じです。