यहां जावा कार्यान्वयन है जो ओ (न्यूनतम (एन, एम)) संचालन ~ ओ (एन) जैसे कुछ में लंबाई एन और एम के साथ दो तारों के बीच अधिकतम ओवरलैप पाता है।
मेरे पास @ sepp2k: s अब हटाए गए उत्तर के समान विचार था, और इस पर थोड़ा आगे काम किया। ठीक काम करने लगता है। विचार पहली स्ट्रिंग के माध्यम से फिर से शुरू करना है और दूसरी स्ट्रिंग की शुरुआत से मेल खाने वाला कुछ खोजने के बाद ट्रैकिंग शुरू करना है। यह पता लगाया गया है कि झूठे और सच्चे मैचों ओवरलैपिंग होने पर आपको एकाधिक एक साथ ट्रैकिंग करने की आवश्यकता हो सकती है। अंत में आप सबसे लंबा ट्रैक चुनते हैं।
मैचों के बीच अधिकतम ओवरलैप के साथ, मैंने अभी तक सबसे खराब मामले का काम किया है, लेकिन मुझे उम्मीद है कि यह नियंत्रण से बाहर हो जाएगा क्योंकि मुझे लगता है कि आप मनमाने ढंग से कई मैचों को ओवरलैप नहीं कर सकते हैं। आम तौर पर आप एक समय में केवल एक या दो मैचों को ट्रैक करते हैं: जैसे ही कोई मेल नहीं होता है, उम्मीदवारों को हटा दिया जाता है।
static class Candidate {
int matchLen = 0;
}
private String overlapOnce(@NotNull final String a, @NotNull final String b) {
final int maxOverlap = Math.min(a.length(), b.length());
final Collection<Candidate> candidates = new LinkedList<>();
for (int i = a.length() - maxOverlap; i < a.length(); ++i) {
if (a.charAt(i) == b.charAt(0)) {
candidates.add(new Candidate());
}
for (final Iterator<Candidate> it = candidates.iterator(); it.hasNext();) {
final Candidate candidate = it.next();
if (a.charAt(i) == b.charAt(candidate.matchLen)) {
//advance
++candidate.matchLen;
} else {
//not matching anymore, remove
it.remove();
}
}
}
final int matchLen = candidates.isEmpty() ? 0 :
candidates.stream().map(c -> c.matchLen).max(Comparator.comparingInt(l -> l)).get();
return a + b.substring(matchLen);
}
private String overlapOnce(@NotNull final String... strings) {
return Arrays.stream(strings).reduce("", this::overlapOnce);
}
और कुछ परीक्षण:
@Test
public void testOverlapOnce() throws Exception {
assertEquals("", overlapOnce("", ""));
assertEquals("ab", overlapOnce("a", "b"));
assertEquals("abc", overlapOnce("ab", "bc"));
assertEquals("abcdefghqabcdefghi", overlapOnce("abcdefgh", "efghqabcdefghi"));
assertEquals("aaaaaabaaaaaa", overlapOnce("aaaaaab", "baaaaaa"));
assertEquals("ccc", overlapOnce("ccc", "ccc"));
assertEquals("abcabc", overlapOnce("abcabc", "abcabc"));
/**
* "a" + "b" + "c" => "abc"
"abcde" + "defgh" + "ghlmn" => "abcdefghlmn"
"abcdede" + "dedefgh" + "" => "abcdedefgh"
"abcde" + "d" + "ghlmn" => "abcdedghlmn"
"abcdef" + "" + "defghl" => "abcdefghl"
*/
assertEquals("abc", overlapOnce("a", "b", "c"));
assertEquals("abcdefghlmn", overlapOnce("abcde", "defgh", "ghlmn"));
assertEquals("abcdedefgh", overlapOnce("abcdede", "dedefgh"));
assertEquals("abcdedghlmn", overlapOnce("abcde", "d", "ghlmn"));
assertEquals("abcdefghl", overlapOnce("abcdef", "", "defghl"));
// Consider str1=abXabXabXac and str2=XabXac. Your approach will output abXabXabXacXabXac because by
// resetting j=0, it goes to far back.
assertEquals("abXabXabXac", overlapOnce("abXabXabXac", "XabXac"));
// Try to trick algo with an earlier false match overlapping with the real match
// - match first "aba" and miss that the last "a" is the start of the
// real match
assertEquals("ababa--", overlapOnce("ababa", "aba--"));
}
तार की औसत लंबाई क्या है? – RBarryYoung
केवल मध्य स्ट्रिंग लंबा है, औसतन 100 वर्ण। उपसर्ग और पोस्टफिक्स केवल 20 वर्ण हैं। यह वास्तव में कोई फर्क नहीं पड़ता। डेटाबेस रूपांतरण केवल एक बार होता है। इसमें कई दिन लगेंगे लेकिन सबसे बुरे मामले में तारों के संयोजन पर केवल कुछ घंटे खर्च किए जाएंगे। मैं सिर्फ मजेदार और चुनौती के लिए इष्टतम समाधान खोजने की कोशिश कर रहा हूं। मुझे लगता है मुझे यह मिल गया है। धन्यवाद! –