Uzun anagram bulmak için Algoritma

5 Cevap php

Kullanıcının yaklaşık 250.000 kelimelik bir sözlük var diyelim. Algoritma bir dizi veya bir dize olarak 12 harf almak ve bir sözlükten uzun sözcüğü maçlar varyasyonu bulmak gerekir.

Tabii ki, bir zaman bunu kaba zorlayabilir, ama ne bunu yapmak için en zarif yolu olurdu acaba?

Bu temel sorun için bir kısayol olarak herhangi bir dil-özel işlevlerini kullanmak istemiyorsanız PHP daha başka dilleri kullanarak cevaplar da kabul edilecektir.

Kelimeler veritabanında saklanır, ama ben hız için belleğe onları çekin: Not. Ben emin değilim ancak PHP'nin indeksleme bir MySQL veritabanı daha iyidir?

5 Cevap

I the anagram question here için cevap biraz değiştirilmiş bir sürümü ile gitmek istiyorum

Sözlükteki her kelime için, alfabetik harfleri sıralamak. Yani "filanca" "abfoor." Olur

Eksiksiz girişi ile başlayın, alfabetik olarak sıralanmış. Onun bulunamadı, tekrar arama yapmak, bir harf çıkarın. Her harf için bunu yapın. Sonra böylece ... iki harf çıkarın ve.

Worst case: No 'anagram' found at all. You will have to test all possible input combinations, which will give you around 2^n lookups where n is the number of input characters (in your example: 12) However, the speed of the algorithm does not depend on the size of the dictionary at run time (of course, sorting the words alphabetically does) which in my opinion is the most important thing here.

Her kelimenin imzasını hesaplamak gerekir, sadece bir kez yapmak ve kelime ile birlikte veritabanına kaydetmek.

Tablo, böyle bir şey olmalı:

   word varchar(12), 
   a int,
   b int, 
   c int,
    ...
   w int,
   z int;

and the fields from a to z have to contains the number of letter contained in the word, for example anagram would have a record like:

word,    a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
anagram, 3,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0

once you have the twelve letters you have to calculate the signature of the set and use it to create a select like this:

select word, length(word) as wordlen
from dictionary
where
a <= 4 and
b <= 0 and
c <= 1 and
d <= 2 and
e <= 0 and
f <= 0 and
 ....
z <= 0
order by wordlen desc;

Eğer varsa set harfi kullanılarak oluşturulabilir tüm kelime için.

No permutation, no combination and the though work (compiling the dictionary) is done only once and offline.

On iki karakter daha uzun olan tüm kelimeleri veritabanından başka bir ipucu, şerit

Eğer uzun eşleşen kelimeyi bulmak için çalışıyorsanız, ben kelime uzunluğu sözlüğü sıralamak için çalışırken başlamak istiyorum, bu yüzden uzun kelimeleri en çok çaba odaklanabilirsiniz

Eric Lippert'ın bilgilendirici bir blog post yaklaşık evirmece arama yazmıştır. Örneklerin hepsi c # kullanmak, ancak teknikler herhangi bir dilde kullanılabilir.

Verimli bir sözlükte anagrams aramaya hile tüm anagramlarının sadece farklı sırayla, aynı harfleri sahip olduğunu fark etmektir. Onun harfleri büyük harfle yazılır ve alfabetik sırayla, sonra bir kelime başka bir anagramıdır olup olmadığını kontrol onların kanonik formlarını karşılaştırarak kadar basittir siz "canonicalize" her kelimeyi, böylece eğer

Bu teknik sayesinde, kolayca bir karma tablo veya dengeli ağacından anagramlar bakabilirsiniz.

Benim fikrim:

pseudocode:

int_32 letter_mask
int_32 permutation_match_mask
if(((letter_mask XOR permutation_match_mask) AND letter_mask)  == 0)
        YOU_HAVE_HIT;

de bu lettermask olmayan repetive harfleri varsa çalışır, ama sen Leter ve permutationmatchmask uzatabilirsiniz daha (muhtemelen gibi) daha fazla mektup varsa

DÜZENLEME

Başka bir fikir

Alphabeticaly emriyle kelime sıralama kelime.

Orada 12 letteres ve bunların hepsi tam 4095 doktorunun cobinations var daha farklı ise (sadece özetlemek i = 1 -> 12 binomiyal (12 i üzerinden)) (harfler ABCD için, ABCD, ABC, ABD, ACD (vardır , BCD, AB, AC, AD, BC, BD, CD, A, B, C, D) Ve ben orada 4095 12 farklı harflerle ve daha az bazı harflerin aynı olup olmadığını dedi.

Karmaşıklık 4095 * Log2 aproximetly 75000 nedir (250000). Peki bu denemeye değer.

Her kombinasyonu kesin arama için gidin.