सबसे छोटा आम सुपरस्ट्रिंग


26

तार के देखते हुए एक सूची s_0, s_1, ..., s_nसबसे छोटा स्ट्रिंग लगता है Sकि में से प्रत्येक में शामिल है s_0, s_1, ..., s_nएक के रूप में स्ट्रिंग

उदाहरण :

  • S('LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE')='SEDOLOREMAGNAD'
  • S('ABCDE', 'BCD', 'C')='ABCDE'

सबसे छोटा प्रोग्राम (या फ़ंक्शन) लिखें जो इस समस्या को हल करता है। यदि आप चाहें तो स्ट्रिंग को एरे या कैरेक्टर / पूर्णांकों की सूची के रूप में दर्शा सकते हैं। मानक पुस्तकालय ठीक हैं। इनपुट / आउटपुट के लिए आप जो भी अधिक सुविधाजनक है उसका उपयोग कर सकते हैं: STDIN / STDOUT, उपयोगकर्ता शीघ्र, पैरामीटर / किसी फ़ंक्शन का रिटर्न मान आदि।

प्रदर्शन महत्वपूर्ण नहीं है - मान लीजिए कि कुल लंबाई के इनपुट के लिए <100 वर्ण परिणाम का औसत आधुनिक हार्डवेयर पर <10 सेकंड में गणना की जानी चाहिए।


3
+1 अच्छा सवाल। मेरा सुझाव है कि आप अपेक्षित परिणामों के कुछ अतिरिक्त उदाहरणों को शामिल करें ताकि लोग आसानी से निर्णय ले सकें कि क्या प्रस्तुतियाँ विभिन्न प्रकार के मामलों को संभालने में सक्षम हैं।
डेविड

इनपुट / आउटपुट को कैसे संभाला जाना चाहिए? क्या परिणाम मुद्रित होना चाहिए या किसी फ़ंक्शन से लौटाया जाना चाहिए?
flornquake

इसलिए, नहीं "हर स्ट्रिंग के लिए, यदि इसमें सभी शामिल हैं ..., इसे वापस करें" एक वैध समाधान नहीं है?
जॉन ड्वोरक

मुझे संदेह है कि एक उत्तर होने जा रहा है। यह सवाल स्टैक ओवरफ्लो (कोड-गोल्फ भाग के बिना) पर काफी अच्छी तरह से फिट हो सकता है ।
जॉन ड्वोरक

जवाबों:


8

पायथन 2, 170 153/157/159

बैपटिस्ट के कुछ विचारों के लिए धन्यवाद ।

from itertools import*
print min((reduce(lambda s,w:(w+s[max(i*(s[:i]==w[-i:])for i in range(99)):],s)[w in s],p)
for p in permutations(input())),key=len)

दूसरी लाइन ब्रेक की जरूरत नहीं है।

इनपुट: 'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'
आउटपुट:SEDOLOREMAGNAD

यहां तक ​​कि लंबे इनपुट स्ट्रिंग्स के साथ, यह 2 सेकंड से भी कम समय में चलता है, अगर ज्यादातर 7 इनपुट स्ट्रिंग्स हैं (जैसा कि दिए गए उदाहरण में है, जो मेरी मशीन पर 1.7 1.5 सेकंड में चलता है )। 8 या अधिक इनपुट स्ट्रिंग्स के साथ, हालांकि, 10 से अधिक सेकंड लगते हैं, क्योंकि समय जटिलता है O(n!)

जैसा कि बैपटिस्ट ने बताया, यदि इनपुट की लंबाई का समर्थन किया जाना चाहिए (कोड 157 की कुल लंबाई बनाते हुए) के range(99)साथ प्रतिस्थापित किया range(len(w))जाना चाहिए। यदि खाली इनपुट स्ट्रिंग्स का समर्थन किया जाना चाहिए, तो इसे बदलना होगा range(len(w)+1)। मुझे लगता है कि range(99)200 से कम किसी भी कुल इनपुट लंबाई के लिए सही ढंग से काम करता है, हालांकि।

अधिक परीक्षण:

>>> "AD", "DO", "DOLOR", "DOLORE", "LOREM", "MAGNA", "SED", "ORE",  "R"
SEDOLOREMAGNAD

>>> 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvw
... xyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu
... vwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 'ZOOM', 'aZ', 'Za', 'ZA'
aZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZOOM

5

गणितज्ञ 337 418 372

गणितज्ञों के उपयोग को लागू करने के असफल प्रयास के बाद LongestCommonSubsequencePositions, मैंने पैटर्न मिलान का रुख किया।

v=Length;
p[t_]:=Subsets[t,{2}];
f[w_]:=Module[{c,x,s=Flatten,r={{a___,Longest[y__]},{y__,b___}}:>{{a,y},{y,b},{y},{a,y,b}}},
c=p@w;
x=SortBy[Cases[s[{#/.r,(Reverse@#)/.r}&/@c,1],{_,_,_,_}],v[#[[3]]]&][[-1]];
Append[Complement[w,{x[[1]],x[[2]]}],x[[4]]]]

g[r_]:=With[{h=Complement[r,Cases[Join[p@r,p@Reverse@r],y_/;!StringFreeQ@@y:>y[[2]]]]},
FixedPoint[f,Characters/@h,v@h-1]<>""]

पैटर्न-मिलान नियम,

r={{a___,Longest[y__]},{y__,b___}}:> {{a,y},{y,b},{y},{a,y,b}}},

शब्दों की एक आदेशित जोड़ी लेता है (वर्णों की सूची के रूप में प्रतिनिधित्व) और रिटर्न: (1) शब्द, {a,y}और {y,b}उसके बाद (2) सामान्य प्रतिस्थापन, yजो दूसरे शब्द की शुरुआत के साथ एक शब्द के अंत को जोड़ता है, और, अंत में, संयुक्त शब्द {a,y,b}जो इनपुट शब्दों को बदल देगा। संबंधित उदाहरण के लिए बेलिसरिज़ देखें: /mathematica/6144/looking-for-longest-common-substring-solution

तीन लगातार अंडरस्कोर वर्ण यह संकेत देते हैं कि तत्व शून्य या अधिक वर्णों का एक अनुक्रम है।

Reverseबाद में यह सुनिश्चित करने के लिए नियोजित किया जाता है कि दोनों आदेशों का परीक्षण किया गया है। लिंक करने योग्य पत्रों को साझा करने वाले उन जोड़े को अपरिवर्तित और अनदेखा किया जाता है।

संपादित करें :

निम्नलिखित उन सूची शब्दों से हटाता है जो "दफन" हैं (यानी पूरी तरह से निहित) दूसरे शब्द में, (@ flornquake की टिप्पणी के जवाब में)।

h=Complement[r,Cases[Join[p@r,p@Reverse@r],x_/;!StringFreeQ@@x:> x[[2]]]]

उदाहरण :

 {{"D", "O", "L", "O", "R", "E"}, {"L", "O", "R", "E", "M"}} /. r

रिटर्न

{"D", "O", "L", "O", "R", "E"}, {"L", "O", "R", "E", "M"}, { "L", "O", "R", "E"}, "" D "," O "," L "," O "," R "," E "," M "}}


प्रयोग

g[{"LOREM", "ORE", "R"}]

AbsoluteTiming[g[{"AD", "DO", "DOLOR", "DOLORE", "LOREM", "MAGNA", "SED", "ORE",  "R"}]]

"Lorem"

{0.006256, "SEDOLOREMAGNAD"}


क्या यह इनपुट के लिए काम करता है "LOREM", "ORE", "R"?
flornquake

(Ie, यह सही उत्पादन का उत्पादन करता है "LOREM"?)
flornquake

@flornquake। अच्छा पकड़ा। मैंने इसे वर्तमान संस्करण में संबोधित किया। मुझे आशा है कि मैंने अन्य मामलों को याद नहीं किया है। धन्यवाद।
डेविड

और कुछ नहीं पर उत्तम!
डेविड

3

GolfScript, 66 अक्षर

{.,1>{.`{[1$]-s:h;.,),\`{:g<`{\+.g?0<{;}*}+h%~}+/}+%.&}*}:s~{,}$0=

बहुत कम है, लेकिन घातीय समय जटिलता (और गोल्फस्क्रिप्ट) के कारण वास्तव में धीमा है, यह 10 सेकंड की समय सीमा को तोड़ता है।

उदाहरण:

['LOREM' 'DOLOR' 'SED' 'DO' 'MAGNA' 'AD' 'DOLORE']
{.,1>{.`{[1$]-s:h;.,),\`{:g<`{\+.g?0<{;}*}+h%~}+/}+%.&}*}:s~{,}$0=
# => SEDOLOREMAGNAD

['AB' 'BC' 'CA' 'BCD' 'CDE']
{.,1>{.`{[1$]-s:h;.,),\`{:g<`{\+.g?0<{;}*}+h%~}+/}+%.&}*}:s~{,}$0=
# => CABCDE

2

अजगर 2, 203 187 200

from itertools import permutations as p
def n(c,s=''):
 for x in c:s+=x[next((i+1 for i,l in [(j,x[:j+1])for j in range(len(x))][::-1]if s.endswith(l)),0):]
 return s
print min(map(n,p(input())),key=len)

इनपुट: ['LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE']
आउटपुट:SEDOLOREMAGNAD

संपादित करें

उपयोग reduceऔर कुछ गंदे आयात की प्रवंचना के कारण, मैं इसे और भी कम कर सकता हूँ (और केवल एक पंक्ति में!)

print min((reduce(lambda a,x:a+x[next((i+1 for i,l in [(j,x[:j+1])for j in range(len(x))][::-1]if a.endswith(l)),0):],P,'')for P in __import__('itertools').permutations(input())),key=len)

संपादित करें 2

जैसा कि उल्लेख किया गया है, यह गलत परिणाम देता है जब एक शब्द दूसरे में निहित होता है। इस के लिए तय एक और 13 वर्ण कहते हैं:

print min((reduce(lambda a,x:a+(x[next((i+1 for i,l in [(j,x[:j+1])for j in range(len(x))][::-1]if a.endswith(l)),0):],'')[x in a],P,'')for P in __import__('itertools').permutations(input())),key=len)

यहाँ साफ किया गया संस्करण है:

from itertools import permutations

def solve(*strings):
    """
    Given a list of strings, return the shortest string that contains them all.
    """
    return min((simplify(p) for p in permutations(strings)), key=len)

def prefixes(s):
    """
    Return a list of all the prefixes of the given string (including itself),
    in ascending order (from shortest to longest).
    """
    return [s[:i+1] for i in range(len(s))]
    return [(i,s[:i+1]) for i in range(len(s))][::-1]

def simplify(strings):
    """
    Given a list of strings, concatenate them wile removing overlaps between
    successive elements.
    """
    ret = ''
    for s in strings:
        if s in ret:
            break
        for i, prefix in reversed(list(enumerate(prefixes(s)))):
            if ret.endswith(prefix):
                ret += s[i+1:]
                break
        else:
            ret += s
    return ret

print solve('LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE')

सैद्धांतिक शुद्धता की कीमत पर कुछ पात्रों का मुंडन संभव है, range(99)इसके बजाय इसका उपयोग करके range(len(x))(इस एक के बारे में सोचने के लिए क्रेडिट)।


यदि आप शुद्धता का त्याग करने के लिए तैयार हैं तो आप लालची दृष्टिकोण या 2 दृष्टिकोण के बहुपद सन्निकटन कारक का उपयोग कर सकते हैं।
पीटर टेलर

अच्छा समाधान! आपको यह जांचने की आवश्यकता है कि क्या नए शब्द पहले से ही सुपरस्ट्रिंग में हैं, हालांकि: 'LOREM', 'ORE', 'R'गलत तरीके से आउटपुट का उत्पादन करता है LOREMORER
flornquake

@flornquake अच्छा कैच। मैं इसे ठीक करने में कामयाब रहा लेकिन इसमें 13 किरदार शामिल हैं।
बैप्टिस्ट एम।

1

अजगर, 144 चरस

S=lambda A,s:min(S(A-set([a]),s+a[i:])for a in A for i in range(len(a)+1)if i==0 or s[-i:]==a[:i])if A else(len(s),s)
T=lambda L:S(set(L),'')[1]

Sऐसे शब्दों का एक सेट लेता है, Aजिन्हें अभी भी रखने की आवश्यकता होती है और एक स्ट्रिंग होती है, sजिसमें अब तक शब्द होते हैं। हम एक शेष शब्द लेने aसे Aऔर से यह ओवरलैप 0करने len(a)के अंत के साथ पात्रों s

दिए गए उदाहरण पर केवल 0.15 सेकंड लगते हैं।


बहुत अच्छे! लेकिन कुछ अन्य समाधानों की तरह, यह इनपुट की तरह काम नहीं करता है ['LOREM', 'ORE', 'R']। मैंने यह तय करने के लिए स्वतंत्रता ली है कि और आपके समाधान को कुछ और बढ़ाएँ: S=lambda A,s='':A and min((S(A-{a},(s+a[max(i*(s[-i:]==a[:i])for i in range(len(a))):],s)[a in s])for a in A),key=len)or s(दूसरी पंक्ति की आवश्यकता नहीं है)। उपयोग: S({'LOREM', 'DOLOR', 'SED', 'DO', 'MAGNA', 'AD', 'DOLORE'})रिटर्न 'SEDOLOREMAGNAD'
'16:

0

हास्केल, 121

import Data.List
a p []=[(length p,p)]
a p s=[r|w<-s,t<-tails w,isInfixOf w$p++t,r<-a(p++t)(s\\[w])]
s=snd.minimum.a ""

यदि फ़ंक्शन को नाम से बाध्य होने की आवश्यकता नहीं है, तो माइनस दो

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.