eşleşen başlangıç ​​ve bitiş harfleriyle en uzun kelime listesi


11

Arkadaşım bana kolay olduğunu söylediği bir sorun verdi, ama bunu yapmak için kullanmak için iyi bir algoritma bulamıyorum.

Size 100 rastgele İngilizce kelimeden oluşan bir giriş verilir. Bir kelimedeki son harfin bir sonraki kelimedeki ilk harfle eşleştiği en uzun kelime dizesini bulmanız gerekir. Her kelimeyi yalnızca bir kez kullanabilirsiniz.

Örneğin, size "kedi", "köpek", "o" kelimeleri verildiyse, yapabileceğiniz en uzun dize "kedi -> o" olur. Size "fare", "geyik", "tek boynuzlu at" kelimeleri verildiyse, yapabileceğiniz en uzun dize sadece bir kelime olacaktır (bu kelimelerin hiçbiri bağlantı vermediğinden). Size "kuş", "yemek", "harb" kelimeleri verildiyse, yapabileceğiniz en uzun dize "harb -> kuş -> çanak" (veya "çanak -> harb -> kuş" veya "kuş - > yemek -> harb ").

Bunu yönlendirilmiş bir döngüsel grafik olarak modelleme fikri buldum. Her düğüm sadece bir sözcük olacak ve köşeler bu sözcüğün bittiği harfle başlayan her kelimeye / düğüme gidecektir.

+-------+         \ +------+
|  cat  |-----------| that |
+-------+         / +------+
    |                  |
   \|/                 |
+-------+ /            |
|  the  |--------------+
+-------+ \

Bu sorun , NP-Hard olan en uzun yol araması gibi görünmektedir .

Bunu yapmanın daha iyi bir yolu var mı? Ya da kullanılabilecek bir çeşit yaklaşım algoritması mı? Ya da arama alanını azaltmak için İngilizce niteliklerinden yararlanmanın bir yolu var mı?


4
100 kelimeyle, (en azından) 100 elde edersiniz! = 9.332622e + 157 kombinasyon. Bu konuda iyi şanslar, sanırım arkadaşınız bacağınızı çekiyor, bu kolay.
Martin Wickman

1
Ancak, olası kombinasyonların sayısı bundan daha azdır, çünkü ortalama olarak tek bir kelime sadece yaklaşık 6 veya 7 başka kelimeyle bağlantılıdır.
Abe Aracı

2
Bunun tam olarak en uzun yol araması olduğu konusunda haklısınız. Bence arkadaşın yanlış. Ancak, kapsamlı bir aramanın kodlanması zor değildir ve bu kadar uzun sürebilir.
kevin cline

4
Sadece eğlenmek için, Ruby'de kaba bir kuvvet kapsamlı arama (@kevincline'nin işaret ettiği gibi) kodladım ( gist.github.com/anonymous/6225361 ). 100 kelimeyle sadece 96 saniye sürdü ( gist.github.com/anonymous/6225364 ). Ve bu son derece verimsiz, optimize edilmemiş, yorumlanmış, hızlı ve kirli bir betikti. Yani sadece 100 kelime ile kaba kuvvetin yavaş bir versiyonu bile aklı başında bir zaman içinde çalışır. Kodum aslında çevrimsel olmayan bir grafik oluşturmaz ve sonra onu arar, her kelimeden başlayarak olası her yolu özyinelemeli olarak oluşturur ve en uzun olanları izler.
Ben Lee

3
Sorun, 100 kelime olduğunu belirtiyor. Bu, bahsettiğiniz makalede belirtilen dinamik bir programlama çözümü uygulayabileceğiniz anlamına geliyor.
Julien Guertault

Yanıtlar:


5

Sanırım bu, bahsettiğiniz en uzun yol (LP) sorunuyla ilgili, ancak biraz farklı. Birincil fark LP probleminin önerdiğiniz problemden daha yüksek derecede bağlantıya sahip olmasıdır. Son ve ilk harflerle bağlantılarınızı kısıtlayarak çok sayıda olası kombinasyonu kaldırırsınız.

İşte bu bir mücadele öneriyoruz:

  1. Listedeki her kelime için, olası bağlantıları ve bağlantıları dışarı sayın.
  2. 0 giriş ve 0 çıkış içeren kelimeleri atın.
  3. En düşük giriş ve çıkış sayılarına sahip bir başlangıç ​​"başlangıç ​​sözcükleri" kümesi belirleyin ve çıkışlar 0'dan büyük olmalıdır.
  4. Her başlangıç ​​kelimesi ins / out bağlantı sayısının kendi çalışma kopyasını alır. Bu zincirin başını oluşturur.
  5. Her zincir için, aşağıdakilere dayalı olarak "sonraki kelimelerin" bir listesini tanımlayın:
    • başlangıç ​​veya önceki kelimenin son harfi
    • en düşük giriş ve çıkış bağlantısı sayısı (yine, çıkışlar 0'dan büyük olmalıdır)
  6. Her biri için next word, zincir sonlanıncaya kadar 5. adımı tekrarlayın.

Unutmayın:

  • Zincirlerin uzunluğunu takip etmeniz ve en uzun zinciri tanımlamak için küresel bir mekanizmaya sahip olmanız gerekir.

  • Yinelenen bir döngüden kaçınmak için her bir sözcüğü bağlantı sayılarının çalışma kopyasından kaldırmanız gerekir.

  • Bir noktada, zinciriniz sona erecek ve 0 bağlantı çıkış sayısı olan bir kelime seçmelisiniz.

  • Kelimeler çalışma listelerinden kaldırıldıkça giriş / çıkışları yeniden hesaplamanız gerekebilir. İlk bakışta, genel setler nispeten küçük olacağından bunun gerekli olacağını düşünmüyorum. 1000 kelimeye kadar ölçeklendirdiyseniz, statik sayımlara sahip olmak algoritmanın birleşmesini yavaşlatabilir.

Bunu bir paketleme problemi olarak gördüm. Bana göre, içeri ve dışarı bağlantılar paketlenecek şekli tanımlar. Bağlantılar ne kadar düşük olursa şekil o kadar tuhaf olur. Şekil ne kadar tuhaf olursa, o kadar çabuk paketlemek istiyorum, daha sonra zincire girdikten sonra tuhaf bir şekil alabilme ihtimaline sahip olduğumu algıladım.

Örnek olarak:

{dog, gopher, alpha, cube, elegant, this, that, bart}

dog     0, 1
gopher  1, 0
alpha   0, 0
cube    0, 1
elegant 1, 2
this    3, 0
that    2, 1
bart    0, 2

//alpha is dropped with 0 in and 0 out.
//two candidates found: dog, cube

//chain 1
dog => gopher
//chain 2
cube => elegant => that => this

//Note 1: the following chain won't occur due to selection rules
//that takes priority over this because of output count
cube => elegant => this

//Note 2: this chain won't occur either due to selection rules
bart => that => this

2
Bu algoritmanın her zaman en uzun yolu bulacağının garantisi var mı? Başımın tepesinden bir karşı örnek düşünemiyorum, ama bu "yerel maksimum" tipte bir çözüm için düşebilir gibi görünüyor.
Ben Lee

@BenLee - Ben bir yazılım mühendisiyim; Kodumu asla garanti etmiyorum. :-) Cidden, sorunuzun cevabını bilmiyorum. Belirlenen teorim ve matematiksel kanıt becerilerim zayıftır, hafifçe söylemek gerekirse, algoritmamı doğrulamak için ampirik değerlendirmenin ötesinde bir yolum yok. Bu sorunun gerçekten NP zor olduğundan emin değilim, ama bu iddiayı da doğrulayamıyorum. NP-zor değilse, algoritmayı doğrulamak için bir araç olmalıdır.

2
Böyle bir kelime listesine ne dersiniz: "köpek, gopher, topuz, rahibe, öğlen, nub". Algoritma, "topuz, rahibe, öğlen, nub" ın herhangi bir kombinasyonu olduğunda, algoritma en uzun listeyi yanlış olarak "dog -> gopher" olarak seçer.
Abe Aracı

1
@AbeTool - iyi bir örnek var. "En düşük girdi> = 1" ve "en düşük çıktı> = 1" kombinasyonlarına izin vermek için başka bir yineleme (veya iki) eklerdim.

2
Bunun her durumda sorunu çözeceğini sanmıyorum. Bunun "yerel maksimum" tipi bir çözüme düştüğünü düşünüyorum.
Abe Aracı

3

26X26 matrisini, her alfabe ve kenar olarak sözcük olarak yönlendirilmiş köşe grafiğini temsil edecek şekilde yaparsanız. Örneğin, kelime - APPLE A ve E köşelerini A'dan E'ye doğru yönlendirilmiş şekilde bağlayın. Şimdi sorun, grafikte en büyük Eulerian izi (maksimum kenar sayısını içeren, her kenarı bir kez köşelerin tekrarlanmasıyla ziyaret ederek) bulmaya indirgeniyor. O (E) algoritmasından biri, bir çift köşeden rastgele başlamak olacaktır. Aralarında bir yol bulun. Mümkün olana kadar yolu rahatlatmaya devam edin.

update @ GlenH7 www.hackerearth / jda'da benzer bir soruyu son zamanlarda çözdüm, en iyi çözümle ilgili göreceli puanlar vardı ve aşağıdaki yaklaşımla en yüksek puanları aldım-

Verilen kelimelerin listesi. Onlar tarafından oluşturulabilecek en uzun zinciri bulun. Bir zincir, her kelimenin son sözcüğün sonunda biten * bir harfle başlaması durumunda geçerlidir.

Yaklaşım =

1) alfabelerin grafiğini köşeler ve kelimelerin kenarları olarak yapar. Birden fazla kenar kullanmak yerine, kenar sayısına eşit bir ağırlık kullanın.

2) Maksimum kenarlı grafiğin güçlü bir şekilde bağlanmış bileşenini bulun. Diğer kenarları geçici olarak atın.

3) Her köşe için bağımsızlığını geçmişine eşit yapın.

4) Şimdi grafikte öküz devresi var. Bul onu.

5) Şimdi kalan grafikte (wrt orignal grafik seçilen güçlü bağlı bileşende ilk tepe noktası ile en uzun iz bulmak.Bunun NP sert olduğunu düşünüyorum.

6) Elerian devresini izlere dönüştüren Elerian devresine yukarıdaki izi ekleyin.

Neden - Bu sorunun büyük olasılıkla NP zor olduğunu kabul ediyorum (tahmin edin, matematiksel olarak değil). Ancak yukarıdaki yaklaşım, tekdüze dağıtılmış kelimelerin uzun bir listesi (1000+) olduğunda (yani yukarıdaki yaklaşım için wc olması amaçlanmadığında) en iyi sonucu verir. Diyelim ki, verilen listeyi yukarıda belirtilen grafiğe dönüştürdükten sonra, neyse ki bir eulerian grafik olduğu ortaya çıkıyor ( koşullar için http://en.wikipedia.org/wiki/Eulerian_path ), o zaman şüphesiz bu cevabı söyleyebiliriz yukarıdaki soru P'dir ve aslında grafikteki eulerian yoludur ( bunu yapmak için çok basit bir yaklaşım için http://www.graph-magics.com/articles/euler.php adresine bakın ve grafiğinizin tek http://www.geeksforgeeks.org/strongly-connected-components/ve diğer küçük scc'leri geçici olarak temizlemezse, çünkü tek scc için euler yolu vardır). Bu yüzden şanslı olmayan vakalar için (neredeyse tüm vakalar) onları şanslı vakalara dönüştürmeye çalışırım (yani, eulerian iz koşulu yerine getirilir). Bu nasıl yapılır? Alakasız kenarlar için artan derinlik araması yapmayı denedim (verimden daha büyük olan tepe noktasından başlayarak ve gittikçe daha büyük olan tepe noktasında biten bir yoldaki kenar kümesi). Artan derinlik araması, önce yoldaki bir kenarın tümünü, yoldaki iki kenardan daha fazla aradığım anlamına gelir. İlk bakışta, derinlik aramasının O (düğümler ^ i) alacağını ve dolayısıyla şanslı bir durum olana kadar O'nun (düğümler + düğümler ^ 2 + düğümler ^ 3 + ....) toplam zaman karmaşıklığını alacağı görünebilir. Ancak itfa edilmiş analiz, O (kenarlar) olduğunu ortaya çıkaracaktır. Bir kez azalır şanslı durumda bul eulerian devre.

Buraya kadar hepsi polinom zamanıydı. Bu neredeyse en iyi çözümü verecektir. Ancak çözümünüzü daha da arttırmak için (mükemmel çözüm NP serttir), seçilen scc'deki köşe noktalarından birine bakarak uzun bir yol bulmak için kalan grafikte bazı açgözlü yaklaşımları deneyin. Şimdi bunu daha da arttırmak için yukarıda bulunan eulerian izine ekleyin.


GlenH7 Geçenlerde www.hackerearth / jda üzerinde benzer bir soru çözmüş @, orada en iyi çözümü açısından göreceli işaretleri ve ben şu approch- ile yüksek notları attı
vishfrnds

0

Fikir:

İlk olarak, alfabe harflerinden kelimelere kadar iki harita (karma) oluşturun, örneğin, S ve E; birincisi, S, harfleri kelimelere eşler, ikincisi E, bitiş harfleriyle aynı şeyi yapar.

Örneğin, sözlük şunlardan yapılmışsa:

kuş, tabak, köpek, harb

sahibiz:

S:

a -> [ ]
b -> [ bird ]
c -> [ ]
d -> [ dish, dog ]
...
h -> [ harb ]
...

ve,

E:

a -> [ ]
b -> [ harb ]
c -> [ ]
d -> [ bird ]
...
g -> [ dog ]
h -> [ dish ]
...

Daha sonra, hızlı aramalar için S ve E'yi kullanarak, her kelimede kökleri olan ve bir kelimenin bir ağaçta birden fazla görünmesine izin vermeyecek şekilde, sözlükle aynı boyutta bir orman (ağaç kümesi) oluşturun. onları inşa ederken ağaçların derinlikleri:

bird (depth: 2)
   dish
      harb
   dog

dish (depth: 3)
   harb
      bird
         dog

dog (depth: 0)

harb (depth: 2)
   bird
      dish
      dog

Son olarak, orman üzerinde tekrarlayın ve en derin ağaç (lar) ı bulun.

Çözelti (ler) bu ağaçların soy ekseninde olacaktır.

Örneğin,

dish / harb / bird / dog

Yukarıda.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.