最も一般的な部分文字列


30

入力として文字列のリストを受け取り、すべての入力文字列の部分文字列である最長の文字列を出力するプログラムまたは関数を作成します。同じ長さの部分文字列が複数あり、部分文字列がなくなった場合は、いずれかを出力します。

  • これは、空の文字列を出力することを意味する場合があります。
  • 有効な出力が複数ある場合は、いずれかを出力できます。出力が常に有効である限り、特定の入力に対して一貫した出力を提供する必要はありません。
  • 入力には常に少なくとも1つの文字列がありますが、空ではない文字列が存在しない場合があります。
  • すべての印刷可能なASCII文字が入力に表示される場合があります。表示されるのはこれらの文字のみであると想定できます。
  • デフォルトのメソッドのいずれかを使用して、入力を取得したり出力を生成したりできます。
  • 標準抜け穴は許可されていません。
  • これは -コードのバイト数が少ないほど良いです。

テストケース:

[Inputs] -> [Valid outputs (choose one)]

["hello", "'ello"] -> ["ello"]
["very", "much", "different"] -> [""]
["empty", "", "STRING"] -> [""]
["identical", "identical"] -> ["identical"]
["string", "stRIng"] -> ["st", "ng"]
["this one", "is a substring of this one"] -> ["this one"]
["just one"] -> ["just one"]
["", "", ""] -> [""]
["many outputs", "stuptuo ynam"] -> ["m", "a", "n", "y", " ", "o", "u", "t", "p", "s"]
["many inputs", "any inputs", "ny iii", "yanny"] -> ["ny"]
["%%not&", "ju&#st", "[&]alpha_numeric"] -> ["&"]


2
@Adámその質問は、部分文字列ではなく、最長の共通部分列を求めます。
ドアノブ

1
文字列は英数字のみ、またはアルファベットのみ、または印刷可能ASCIIのみになりますか?
無知の具現化

@EmbodimentofIgnoranceすべての印刷可能なASCII文字を入力に表示できます。
サラJ

2
@Shaggy一般的に、いいえ。2つを区別できる場合、undefined有効な出力文字列がないことを意味します。空の文字列(または他の文字列)が有効な出力である場合、有効な出力がないと主張するのは正しくありません。
サラJ

回答:


8

Python 2、82バイト

f=lambda h,*t:h and max(h*all(h in s for s in t),f(h[1:],*t),f(h[:-1],*t),key=len)

オンラインでお試しください!

飛び散った入力を取ります。最初の文字列が長い入力ではタイムアウトします。

アイデアは最初のストリングの部分ストリングを取っhて残りのすべてのストリングに現れる最も長いものを見つけることtです。そのために、の最初または最後の文字を削除するときに再帰的に分岐しhます。


Python 2、94バイト

lambda l:max(set.intersection(*map(g,l)),key=len)
g=lambda s:s and{s}|g(s[1:])|g(s[:-1])or{''}

オンラインでお試しください!

より直接的な方法。補助関数gはのすべての部分文字列のセットを生成しs、メイン関数はそれらの交点で最も長い文字列を取ります。


8

Brachylog(v2)、3 9バイト

{sᵛ}ᶠlᵒtw

オンラインでお試しください!

完全なプログラム。標準入力からの入力(JSON形式の文字列のリストとして)、標準出力への出力。

説明

{sᵛ}ᶠlᵒtw
 s         Find a substring
  ᵛ          of every element {of the input}; the same one for each
{  }ᶠ      Convert generator to list
     lᵒt   Take list element with maximum length
        w  Output it

どうやら、タイブレークの順序sはBrachylogの他のほとんどすべての順序ではないため、最長の出力を生成するには手動でオーバーライドする必要があります。(これは少しイライラします:Brachylogは2つのメタ述語を連続して解析しないため、オーバーライドのための4つの余分な文字と2つのグループ化文字。)

Brachylog sは空の部分文字列を返さないので、それを回避するためのちょっとしたコツが必要です:関数のサブミット(通常行われること)を行う代わりに、完全なプログラムを作成して標準出力に出力します。そうすれば、共通の部分文字列がある場合は、それを出力するだけで完了です。共通のサブストリングがない場合、プログラムはエラーになりますが、標準出力には何出力されないため、意図したとおりにヌルストリングが出力されます。


1
入力[[多くのinpuabts]、[任意のinabputs]、[ny iabii]、[yanabny]]でこれを試しました。結果はabnyになると予想しました。ただし、結果はaのみです。私は何か間違っていますか?
t-clausen.dk

1
ええと、タイブレークの順序がs間違っていることを思い出したようです。タイブレークの順序をオーバーライドするのは、バイト単位でかなりコストがかかります。とにかく、今すぐそれを行うと、答えが正しいことが重要だからです。どういうわけか、私が試したテストケースはどれも違いに気づきませんでした。
ais523

1
@ ais523順序sは部分文字列を生成し、最初に入力のすべてのプレフィックスを指定し(最初に最長)、次に最初のプレフィックスを削除して繰り返します
Kroppeb

5

ゼリー12 6バイト

Ẇ€f/ṫ0

オンラインでお試しください!

6バイトを節約してくれた@JonathanAllanに感謝します!


Ẇ€œ&/Ṫḟ0部分文字列はすでに長さで順序付けされているため、ジョブを実行して4バイトを節約すると信じています。したがって、フィルタリング結果は次のようになります。残っているのは、一致するものがない場合、tailがゼロを生成することです。また、文字のリストが保証されているため、それらを単純に除外できます。
ジョナサンアラン

またœ&/f/ここで別のものを保存することで置き換えることができると思います
ジョナサンアラン

空のリストを削減した結果を(TypeErrorを上げるのではなく)空のリストにするために、プルリクエストを(できれば)送信しました。それが統合されると、この答えはで6バイトになると思いẆ€f/ṛ/ます。
ジョナサンアラン

@JonathanAllanはいいですね。他のヒントをありがとう-それらを取り入れてくれて嬉しいです。
ニックケネディ

はい、これらのコメントの私の理由は、あなたの投稿にアイデアを取り入れることを許可することでした。
ジョナサンアラン

5

Ruby 2.6、76 59 54バイト

->a{*w=a;w.find{|r|w<<r.chop<<r[1..];a.all?{|s|s[r]}}}

オンラインでお試しください!-Ruby 2.5バージョン(56バイト)

どうやって?

最初に元の配列に設定された潜在的な一致のリストを作成します。リストを反復処理し、文字列が一致しない場合は、リストの末尾に2つの新しい文字列を追加し、最初または最後の文字を切り取ります。最後に一致(最終的には空の文字列)が見つかります。

-2バイトのキリルLと、さらに-2バイトのhistocratに感謝します。


4

R119の 116 108 106バイト

function(S,`?`=nchar,K=max(?S),s=Reduce(intersect,lapply(S,substring,0:K,rep(0:K,e=K+1))))s[which.max(?s)]

オンラインでお試しください!

各文字列のすべての部分文字列を見つけ、部分文字列の各リストの共通部分を見つけ、最後に(の)最も長いものを返します。

キリルLのおかげで-3バイト

代わりに-8バイトを使用lapply Map

-2バイト、Kirill L.のおかげで、括弧を削除


確認する時間はありませんが、間違えなければ、2つのオカレンスで単項演算子としてnchar宣言することで何かを保存するのに十分ncharです。
キリルL.

@KirillL。はい、2バイト短くなります。ありがとう!エイリアシングlistも同様に-3バイトを与えます。
ジュゼッペ

また、ブレースをドロップすることもできます-2
キリルL.

@KirillL。ありがとう!プロダクションコードを使用してこれを開始するのが少し心配です...
ジュゼッペ

それはあなたが毎日使用する言語でゴルフをすることの問題です
MickyT

4

05AB1E14 9 8 バイト

€Œ.«ÃéθJ

@Adnanのおかげで-6バイト。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

€Œ       # Get the substring of each string in the (implicit) input-list
       # Right-reduce this list of list of strings by:
    Ã    #  Only keep all the strings that are present in both list of strings
     é   # Sort by length
      θ  # And pop and push its last item
         # The substrings exclude empty items, so if after the reduce an empty list remains,
         # the last item will also be an empty list,
       J # which will become an empty string after a join
         # (after which the result is output implicitly)

1
€Œ.«Ãõªéθは9バイトで動作するはずだと思います。
アドナン

@Adnanちょっと待ってください、減りました。:SIが試してみましたがÅ«Ã.«Ã代わりに使用すべきであることに気づきませんでした。ありがとう!
ケビンクルーッセン

1
実は、私が思うに€Œ.«ÃéθJ8のために働く必要があります
アドナン・

4

Zsh126 ... 96バイト

算術演算から-3バイト、暗示から-6バイト"$@"(roblogicに感謝)、不要な削除から-5 { }バイト、短縮形からfor-1バイト、使用repeatして-1バイトfor s ($b)、本体と連結して-1バイト、-13バイトいくつかの評価ジャンクの繰り返しループを変更します。

for l
eval a=\( \$l\[{1..$#l},{1..$#l}\] \)&&b=(${${b-$a}:*a})
for s ($b)(($#x<$#s))&&x=$s
<<<$x

オンラインでお試しください! オンラインでお試しください! オンラインでお試しください!

すべての可能な部分文字列を配列aに読み込みb、配列aとの交差に設定しますb。コンストラクト${b-$a}$a、最初の反復でのみ置換されます。兄弟の展開とは異なり、設定されているが空の${b:-$a}場合bは置換されません。

for l;                              # implicit "$@"

# === OLD ===
{
    a= i=                           # empty a and i
    repeat $[$#l**2]                # compound double loop using div/mod
        a+=($l[++i/$#l+1,i%$#l+1])  # append to a all possible substrings of the given line
#               1+i/$#l             # 1,1,1...,  1,1,2,2,2,... ...,  n,n
#                       1+i%$#l     # 1,2,3...,n-1,n,1,2,3,... ...,n-1,n
#       a+=( $l[       ,     ] )    # append that substring to the array
# === NEW ===
    eval a=\( \
        \$l\[{1..$#l},{1..$#l}\] \  # The {bracket..expansions} are not escaped
    \) &&
# ===     ===
    b=( ${${b-$a}:*a} )
#         ${b-$a}                   # if b is unset substitute $a
#       ${       :*a}               # take common elements of ${b-$a} and $a
#   b=(               )             # set b to those elements
}
for s ($b)                          # for every common substring
    (( $#x < $#s )) && x=$s         # if the current word is longer, use it
<<<$x                               # print to stdout

このビットはどのように機能しますか?a+=( $l[1+i/$#l,1+i%$#l] )
ロボリック

1
@roblogic今、私はそれをもっと良く説明したと思う、編集をチェックする。アイデアは、n ^ 2にループし、2つのネストされたforループを使用する代わりに/と%を使用することです
GammaFunction

1
あなたはカットすることができるかもしれませんfor l in "$@"単純にfor l;-それは、bashのトリックです
roblogic

zshはbashよりもずっとエレガントです。この素晴らしい配列比較に類似したものはありませんb=(${${b-$a}:*a})}
ロブログ的

1
それを使ってできることはいくつかありますが、それほど人気が​​あるわけではありません。それは、私が出くわすほとんどの質問にzshの答えを追加することを意味します。:P zshを学びたいならman zshexpnman zshparam特にお勧めです。答えを書くときは常に開いています。
GammaFunction

3

Haskell、80バイト

import Data.List
f(x:r)=last$sortOn(0<$)[s|s<-inits=<<tails x,all(isInfixOf s)r]

オンラインでお試しください!

すべてのサフィックス(ゲットtails最初の単語の)x(リスト内に、すべての接頭辞を取るinitsすべての部分文字列を取得するために、これらのサフィックスの)sのをx。それぞれを保つsことをisInfixOf all、残りのリスト内の文字列r。(使用して長さによって、これらのサブストリングをソートトリックを)し、最後を返します。(0<$)


3

Retina 0.8.2、48バイト

M&!`(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)
O#$^`
$.&
1G`

オンラインでお試しください!説明:

M&!`(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)

最初の文字列のサフィックスごとに、他のすべての文字列のサブストリングでもある最長のプレフィックスを見つけます。これらの接尾辞のプレフィックス(つまり、部分文字列)をすべてリストします。一致する部分文字列がない場合は、空の文字列になります。これはとにかく必要なものです。

O#$^`
$.&

部分文字列を長さの逆順に並べ替えます。

1G`

最初の、つまり最も長い部分文字列のみを保持します。


Let nは引数文字列の数です。次に、する(?=(.*\n.*\1)*.*$)必要が(?=(.*\n.*\1){n-1}.*$)ありますよね?テストケース:["very", "different", "much"] -> [""]
mazzy

1
@mazzy問題が表示されない:オンラインで試してみてください!
ニール

それは問題ではありません。で{n}、あなたは、開始と終了パターンを削除して保つことができる(.+)(?=(.*\n.*\1){n}網膜を書き込むことができます場合nよりも短い(?<=^.*).*$
mazzy

@mazzy Retina 0.8.2ではできません。Retina1では、evalをいじる必要がありますが、とにかく長くなります。
ニール

3

TSQLクエリ、154バイト

USE master
DECLARE @ table(a varchar(999)collate Latin1_General_CS_AI,i int identity)
INSERT @ values('string'),('stRIng');

SELECT top 1x FROM(SELECT
distinct substring(a,f.number,g.number)x,i
FROM spt_values f,spt_values g,@ WHERE'L'=g.type)D
GROUP BY x ORDER BY-sum(i),-len(x)

オンラインで試す

CSを含む照合で列 'a'を宣言することにより、大文字と小文字を区別します(大文字と小文字を区別します)。

2540の開始位置(多くは同一)からすべての文字列を分割しますが、有効な値の範囲は1から2070で、開始位置の後に0から22文字で終わります。しかし、パフォーマンスが低下します。

各行番号内のこれらの別個の文字列がカウントされます。最大カウントは、テーブル変数「@」の行数に常に等しくなります。同じカウントで順序を逆にすると、結果の一番上に最も一致する部分文字列が残り、その後に部分文字列の長さが逆になると、ほとんどの一致で一番長い一致が残ります。クエリは、上位1行のみを選択します。

すべての回答を取得するには、クエリの最初の部分を

上位x 1を同点x FROMで選択


3

C#(Visual C#Interactive Compiler)、320 257バイト

l=>(string.Join(",",l.Select(s=>new int[s.Length*s.Length*2].Select((i,j)=>string.Concat(s.Skip(j/-~s.Length).Take(j%-~s.Length))))
.Aggregate((a,b)=>a.Intersect(b)).GroupBy(x=>x.Length).OrderBy(x =>x.Key).LastOrDefault()?.Select(y=>y)??new List<string>()));

オンラインでお試しください!

@Expired Dataと@danaの小道具


関数から文字列を返すことができます。したがって、対話型コンパイラでは、次のようになります 。294バイト
有効期限切れデータ

1
ここでは解決策は、いくつかのバイトをダウンgolfedだ215バイト
期限切れのデータ

@ExpiredData ah perfectこれは私が必要とした例です:)
Innat3



3

Perl 6の62の 60バイト

{~sort(-*.comb,keys [∩] .map(*.comb[^*X.. ^*]>>.join))[0]}

オンラインでお試しください!

私は少しのPerl 6が余分だ理由である、リストのリストに設定された操作を行うことができないイライラだ.comb>>そこに。

もう1つの面倒なことは、maxアイテムを比較するための関数を取得できないことです。つまり、sort代わりに使用する必要があります。コメントで指摘したように、引数max 取ることができますが、max一般的な部分文字列があるときに負の無限大を返すことを考慮する必要があるため、長くなります(オンラインで試してみてください!)。


3
maxOOモードで呼び出されたときの位置、または:by手続き型モードでの名前付き引数のいずれかで、そのような関数(アリティ1)を取ることができます。
ヴェン

2

Japt v2.0a0、8 -hFバイト

Îã f@eøX

3バイトを節約してくれたShaggyに感謝

それを試してみてください

Îã              //Generate all substrings of the first string
 f@             //Filter; keep the substrings that satisfy the following predicate:
   e            //    If all strings of the input...
    øX          //    Contain this substring, then keep it
-h              //Take last element
-F              //If last element is undefined, default to empty string

最後に長さでソートする必要はありません。3バイト節約します。また、-Fデフォルトは空の文字列です。
シャギー


1

Python 3、137バイト

def a(b):c=[[d[f:e]for e in range(len(d)+1)for f in range(e+1)]for d in b];return max([i for i in c[0]if all(i in j for j in c)],key=len)

オンラインでお試しください!


100バイト以上を削るように見える4ではなく、インデントとして単一のスペースを使用することができます。
朝琴シエル





1

Perl 5(-aln0777F/\n/ -M5.01 -MList::util=max)、99バイト

より確実にゴルフができる

map/(.+)(?!.*\1)(?{$h{$&}++})(?!)/,@F;say for grep{y///c==max map y///c,@b}@b=grep@F==$h{$_},keys%h

TIO



1

、30バイト

≔⊟θη≔⁰ζFLη«≔✂ηζ⊕ι¹ε¿⬤θ№κεPε≦⊕ζ

オンラインでお試しください!リンクは、コードの詳細バージョンです。このアルゴリズムは、すべての部分文字列を生成するよりも効率的で短いです。説明:

≔⊟θη

入力リストの最後の文字列を変数にポップします。

≔⁰ζ

部分文字列の開始インデックスをゼロにします。

FLη«

可能なすべてのサブストリング終了インデックスをループします。(実際、これは長さを除いて0からループするため、値は後で調整されます。)

≔✂ηζ⊕ι¹ε

現在の部分文字列を取得します。

¿⬤θ№κε

この部分文字列が他のすべての入力文字列に含まれているかどうかを確認します。

Pε

その後、以前に出力されたサブストリングをオーバープリントします。

≦⊕ζ

そうでない場合は、部分文字列の開始インデックスを増やしてみてください。


1

バッシュ295 .. 175バイト

きれいではありませんが、少なくとも機能します。 オンラインで試す

-37一般的なクリーンアップ-52 zsh回答から盗用することにより-26配列をループに置き換えることにより ; -2 GammaFunctionに感謝します-3 ループから削除i=0for

for l;{ d=${#l}
for((;i<d**2;i++)){ a="${l:i/d:1+i%d}" k=
for n;{ [[ $n =~ $a ]]&&((k++));}
((k-$#))||b+=("$a");};}
for e in "${b[@]}";do((${#e}>${#f}))&&f="$e";done
echo "$f"

コメントのないオリジナルのスクリプトは次のとおりです。


1
続き2:あなたは置き換えることができ((k==$#))&&((k-$#))||。これはまた、あなたが使用することができますk=0に設定するのではなく
GammaFunction

1
私は「きれいではないが、少なくとも機能する」とbashスクリプトのMOであると思います:)
joeytwiddle



0

JavaScript(Node.js)、106バイト

a=>(F=(l,n,w=a[0].substr(n,l))=>l?n<0?F(--l,L-l):a.some(y=>y.indexOf(w)<0)?F(l,n-1):w:"")(L=a[0].length,0)

オンラインでお試しください!

a=>(                      // Main function
 F=(                      //  Helper function to run through all substrings in a[0]
  l,                      //   Length
  n,                      //   Start position
  w=a[0].substr(n,l)      //   The substring
 )=>
 l?                       //   If l > 0:
  n<0?                    //    If n < 0:
   F(--l,L-l)             //     Check another length
  :a.some(                //    If n >= 0: 
   y=>y.indexOf(w)<0      //     Check whether there is any string not containing the substring
                          //     (indexOf used because of presence of regex special characters)
  )?                      //     If so:
   F(l,n-1)               //      Check another substring
  :w                      //     If not, return this substring and terminate
                          //     (This function checks from the longest substring possible, so
                          //      it is safe to return right here)
 :""                      //   If l <= 0: Return empty string (no common substring)
)(
 L=a[0].length,           //  Starts from length = the whole length of a[0]
 0                        //  And start position = 0
)






0

Pyth、16バイト

eolN.U@bZm{s./dQ

オンラインでお試しください!

       m     Q    # Map Q (parsed input) over the following function (lambda d:
          ./d     # Partitions of d (all substrings)
         s        # Reduce on + (make one list)
        {         # deduplicate
    .U            # reduce the result on the following lambda, with starting value result[0]
      @bZ         # lambda b,Z: Intersection between b and Z
                  # Result so far: all common substrings in random order
 o                # sort the resulting sets by the following lambda function:
  lN              # lambda N: len(N)
e                 # last element of that list
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.