最大的通用子字符串


30

创建一个将字符串列表作为输入的程序或函数,并输出最长的字符串,该字符串是所有输入字符串的子字符串。如果有几个长度相等的子字符串,并且不再有子字符串,则输出其中任何一个。

  • 这可能意味着输出空字符串。
  • 如果有多个有效输出,则可以输出其中任何一个。只要输出始终有效,就不需要为给定的输入提供一致的输出。
  • 输入中将始终至少包含一个字符串,但可能不会存在非空字符串。
  • 所有可打印的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字符都可以出现在输入中。
Sara J

2
@Shaggy通常,不。如果可以区分两者,则undefined表示没有有效的输出字符串。如果空字符串(或任何其他字符串)是有效输出,则声称没有有效输出是不正确的。
Sara J

Answers:


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生成set的所有子字符串s,而main函数则在它们的交点中获取最长的子字符串。


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不会连续解析两个元谓词。)

Brachylog s不会返回空的子字符串,因此我们需要一些技巧来解决该问题:我们编写了一个完整的程序,而不是进行函数提交(这通常是完成的操作),输出到标准输出。这样,如果有一个公共子字符串,我们只需输出它,就完成了。如果没有通用的子字符串,则程序会出错-但是它仍然不输出任何内容到标准输出,因此它会按预期输出空字符串。


1
我尝试使用输入[“许多inpuabts”,“任何inabputs”,“ ny iabii”,“ yanabny”]进行了尝试。我期望结果abny。但是只得到了一个结果。难道我做错了什么 ?
t-clausen.dk

1
gh,似乎我记得抢七的顺序是s错的,而按抢七的顺序推销抢七的顺序相当昂贵。尽管如此,现在还是要这样做,因为正确答案很重要。不知何故,我尝试过的所有测试用例都没有注意到差异。
ais523

1
@ ais523顺序s产生子字符串的方法是,首先给出输入的所有前缀(最长的),然后删除第一个并重复
Kroppeb

5

果冻12 6字节

Ẇ€f/ṫ0

在线尝试!

感谢@JonathanAllan节省了6个字节!


我相信Ẇ€œ&/Ṫḟ0这样做会节省四个字节,因为子字符串已经按长度排序,因此过滤后的结果将是:那么剩下的就是,当没有匹配项时,tail会产生一个零,并且由于我们保证有字符列表,因此我们可以简单地过滤掉它们。
乔纳森·艾伦

我也认为œ&/可以替换为f/此处保存另一个
Jonathan Allan

我提交了一个拉取请求,以(希望)使减少一个空列表的结果成为一个空列表(而不是引发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个新字符串,以截去第一个或最后一个字符。最后,将找到一个匹配项(最终是一个空字符串)。

感谢Kirill L提供了-2个字节,感谢historcrat提供了-2个字节


4

[R 119个 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)]

在线尝试!

找到每个字符串的所有子字符串,找到每个子字符串列表的交集,然后最后返回最长的字符串(之一)。

-3个字节,感谢KirillL。

-8个字节使用 lapply 代替 Map

再次感谢Kirill L. -2个字节,删除了花括号


我没有时间检查,但是如果我没记错的话,nchar通过声明nchar为一元运算符,两次出现足以保存某些内容。
Kirill L.

@KirillL。是的,它短了2个字节。谢谢!list类似地,别名给我们-3个字节。
朱塞佩

您也可以放下另一个
KirillL。

@KirillL。谢谢!我有点担心我将开始使用生产代码来实现这一点
Giuseppe

打高尔夫球是您每天使用的一种语言的问题
MickyT

4

05AB1E14 9 8 字节

€Œ.«ÃéθJ

-6个字节,感谢@Adnan

在线尝试验证所有测试用例

说明:

€Œ       # 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尝试过Å«Ã,但没有意识到我应该.«Ã改用..谢谢!
Kevin Cruijssen

1
其实我认为 €Œ.«ÃéθJ应该8.工作
阿德南

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被替换:与它的同级扩展不同,它不会替代set 时的值,而是空值。

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优雅得多。没有什么比这更好的数组比较AFAIKb=(${${b-$a}:*a})}
roblogic

1
您可以使用它做一些整洁的事情,而且它并不那么受欢迎。这意味着我为遇到的大多数问题添加了zsh答案。:P如果你想了解的zsh,我建议man zshexpnman zshparam特别。在写答案时,我总是打开它们。
GammaFunction

3

哈斯克尔,80个字节

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

在线尝试!

获取所有后缀(tails第一个字)x的列表,并采取所有前缀(inits)的后缀来获取所有子sx。请各sisInfixOf all字符串在余下的列表r。按长度的字符串(使用(0<$)伎俩),并返回最后一个。


3

视网膜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"] -> [""]
疯狂

1
@mazzy我看不到问题:在线尝试!
尼尔

这不成问题。与{n}您可以删除开始和结束模式,并保持(.+)(?=(.*\n.*\1){n}如果视网膜允许写n短于(?<=^.*).*$
mazzy

@mazzy我无法在Retina 0.8.2中使用,而在Retina 1中,我不得不搞乱评估,无论如何它可能会更长。
尼尔

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个字符结尾,通过将类型更改为'P'而不是'L',终止位置可以更长一些,但会削弱性能。

计算每个行号中的这些不同的字符串。最高计数将始终等于表变量“ @”中的行数。反转相同计数的顺序将使子字符串具有最多匹配项位于结果的顶部,然后反转子串的长度将使最长匹配项具有最多匹配项的顶部。该查询仅选择前1行。

为了获得所有答案,请将查询的第一部分更改为

选择领带最多的1个x FROM


3

C#(Visual C#中交互式编译器),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的道具


您可以只从函数返回字符串。因此,在Interactive编译器中,它可能看起来像这样: 294个字节
过期的数据

1
这是解决方案,减少了一些字节215字节
过期的数据

@ExpiredData啊完美,这是我需要的示例:)
Innat3



3

Perl 6的62 60个字节

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

在线尝试!

我有点恼火Perl 6的不能做的一组操作上列出的名单,这也就是为什么有一个额外的.comb>>在那里。

另一个烦人的事情是,max不能使用如何比较项目的功能,这意味着我不得不使用它sort正如评论中所指出的,max 可以接受一个参数,但是它的使用时间更长,因为max在存在常见的子字符串时,我必须考虑返回负无穷大(请在线尝试!)。


3
max可以采用这样的功能(尽管arar为1),无论是在OO模式下调用时是按位置,还是:by在过程模式下都使用命名自变量。
Ven

2

普v2.0a0-hF个字节

Îã f@eøX

感谢Shaggy节省了3个字节

试试吧

Îã              //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默认为空字符串。
毛茸茸的

2

Japt -h,8字节

(我可以删除最后3个字节并改用-Fh标志,但我不喜欢使用-F

mã rf iP

尝试运行所有测试用例

mã rf iP     :Implicit input of array
m            :Map
 ã           :  Substrings
   r         :Reduce by
    f        :  Filter, keeping only elements that appear in both arrays
      i      :Prepend
       P     :  An empty string
             :Implicit output of last element


1

Python 2,103个字节

lambda b:max(reduce(set.__and__,[{d[f:e]for e in range(len(d)+2)for f in range(e)}for d in b]),key=len)

在线尝试!

这是一个匿名的lambda,它将每个元素转换为所有子字符串的集合,然后reduce通过设置交集(set.__and__)对其进行处理,然后maxlength 返回该元素。


与一起缩短1个字节set.intersection
ovs



1

JavaScript(ES6), 98  92字节

a=>(g=b=s=>a.every(x=>~x.indexOf(s))?b=b[s.length]?b:s:g(s.slice(0,-1,g(s.slice(1)))))(a[0])

在线尝试!


1

木炭,30字节

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

在线尝试!链接是详细版本的代码。与生成所有子字符串相比,此算法更有效且更短。说明:

≔⊟θη

将输入列表中的最后一个字符串弹出到变量中。

≔⁰ζ

将子串起始索引清零。

FLη«

循环遍历所有可能的子字符串结束索引。(实际上,此长度从0(不包括长度)开始循环,因此稍后会对其进行调整。)

≔✂ηζ⊕ι¹ε

获取当前的子字符串。

¿⬤θ№κε

检查此子字符串是否包含在所有其他输入字符串中。

Pε

如果是,则套印任何先前输出的子字符串。

≦⊕ζ

否则,尝试增加子字符串开始索引。


1

Bash295..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

盖亚(Gaia),15个字节

eḋ¦&⊢⟨:l¦:⌉=¦⟩∇

在线尝试!

e		| eval as code
 ḋ¦		| find all non-empty substrings
   &⊢		| Reduce by set intersection
              ∇	| and return the first element where
      ⟨:l¦:⌉=¦⟩	| the length is equal to the max length

0

PowerShell中165 163 87字节

-76个字节,感谢Nail 出色的regexp

"$($args-join'
'|sls "(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)"-a -ca|% m*|sort Le*|select -l 1)"

在线尝试!

少打高尔夫球:

$multilineArgs = $args-join"`n"
$matches = $multilineArgs|sls "(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)" -AllMatches -CaseSensitive|% matches
$longestOrNull = $matches|sort Length|select -Last 1
"$longestOrNull"




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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.