2个字符串的最长公共前缀


30

编写一个程序,将2个字符串作为输入,并返回最长的公共前缀。这是,所以最短字节的答案会获胜。

Test Case 1:

"global" , "glossary"
"glo"


Test Case 2:

"department" , "depart"
"depart"

Test Case 3:

"glove", "dove"
""

1
另一个很好的测试用例是"aca", "aba"
Morgan Thrapp 2015年

2
您是否需要一个从STDIN输入并打印到STDOUT的完整程序,或者功能是否正常?
xnor

2
我们可以假设输入内容没有换行符吗?输入将包含哪些字符?
Downgoat

5
一般说明:使用基于正则表达式的解决方案的人不应在未经您自己测试的情况下复制他人的正则表达式答案。这不适用于所有正则表达式引擎。特别是,它在nvi和vim中给出了不同的答案(均不正确)。
Random832

1
给出的所有示例均为小写字母,但是我们是否需要担心大小写差异?例如,应该globalGLOSSARYreturn glo''
AdmBorkBork 2015年

Answers:


22

Python 3,54个字节

感谢Python具有此任务的内置功能!:D

import os;print(os.path.commonprefix(input().split()))

将输入作为两个单词,并用空格分隔,例如glossary global


21

Haskell,29个字节

(c:x)%(d:y)|c==d=c:x%y;_%_=""

用法:

>> "global"%"glossary"
"glo"

%通过模式匹配来递归定义二进制函数。在两个首字母相等的字符串上,采用该首字母,并将其附加到其余字符串的功能上。在其他任何东西上,给出空字符串。


11

Pyth,8个 7字节

e@F._MQ

感谢@isaacg关闭1个字节

接受带引号且逗号分隔的输入,例如"abc", "acc"。当结果为空字符串时,将退出错误(但将stdout留空)。如果那是不可接受的,则添加2个字节用于#e@F._MQq

测试套件

说明

e@F._MQ        : implicit Q = eval(input)
   ._MQ        : Map the prefix operator onto both inputs
 @F            : Fold the setwise intersection operator over those lists
e              : Take the last such element, the prefixes are always made from shortest
               : to longest, so this always gives the longest matching prefix

要使结果成为没有错误的空字符串:e|@F._M.z]k
kirbyfan64sos

@ kirbyfan64sos我相信围绕它的内容#...q要少一个字节,我将在完整代码中进行编辑,我想这很令人困惑
FryAmTheEggman 2015年

1
以输入的形式"abc", "def",你可以使用Q,而不是.z
isaacg

10

C ++,101个 100 99字节

#include<iostream>
int i;main(){std::string s,t;std::cin>>s>>t;for(;s[i]==t[i];std::cout<<s[i++]);}

从中读取两个字符串stdin,从其中一个字符串中打印当前位置的字符,而当前位置的字符等于另一字符串中相同位置的字符。

感谢Zereges节省了一个字节。


4
这是对for声明的一种美丽而可怕的使用……
Joshpbarron

如果字符串相等,则循环将无法终止。
Jon Trauntvein 2015年

2
不适用于包含空格的字符串。您可以通过int i在全局空间中创建来保存一个字节(这样它将被初始化为0)
Zereges 2015年

@JonTrauntvein我认为这是UB(?)。虽然对我有效。(gcc-5.1)
sweerpotato 2015年

9

Haskell,38个字节

((map fst.fst.span(uncurry(==))).).zip

用法示例:( ((map fst.fst.span(uncurry(==))).).zip ) "global" "glossary"-> "glo"

将两个输入字符串压缩成一个成对的字符列表。从中列出两个清单:第一个清单从头开始所有对,只要两个字符都相等,第二个清单所有其余。删除第二个列表,并从第一个列表中提取所有字符。


9

CJam,12 11 9字节

l_q.-{}#<

这将读取两行以Unix样式的行结尾的字符串,即<string>\n<string>\n

感谢-1字节的@MartinBüttner和-2字节的@ jimmy23013!

CJam解释器中在线尝试。

怎么运行的

l_         e# Read a line (w/o trailing LF) from STDIN and push a copy.
  q        e# Read another line from STDIN (with trailing LF).
           e# The trailing linefeed makes sure that the lines are not equal.
   .-      e# Perform vectorized character subtraction. This yields 0 for equal
           e# characters, a non-zero value for two different characters, and the
           e# characters themselves (truthy) for the tail of the longer string.
     {}#   e# Find the index of the first truthy element.
        <  e# Keep that many characters from the first string.

该死,我不敢相信我的第一个答案是如此接近!
geokavel

1
您可以假设尾随换行符并使用来作弊l_q.-
jimmy23013 2015年

@ jimmy23013这是在类似Unix的OS上输入的标准,为什么不呢?谢谢!
丹尼斯

8

APL,13

{⊃↓K/⍨=⌿K←↑⍵}

此函数采用两个字符串组成的数组,并返回前缀:

      {⊃↓K/⍨=⌿K←↑⍵}'glossary' 'global'
glo
      {⊃↓K/⍨=⌿K←↑⍵}'department' 'depart'
depart

说APL字母表是字节大小字符的字母表真的很公平吗?还是这附近的标准做法?
Filipq

9
@Filipq答案在这里使用对该语言最自然的编码。APL有其自己的代码页,每个字符都是一个字节。
Alex A.

7

AppleScript,215字节

我非常努力...;(

设置x为(显示对话框““默认答案”“)的文本返回
设置返回到(显示对话框““默认答案”“)的文本
设置为1
设置为“”
在x的项n = a的项n时重复
将o设置为o&x的项目n
将n设置为n + 1
结束
Ø

我想看到的AppleScript能如何退出这个功能,并且是它没有内置字符串比较。


12
AppleScript并不是为任何目的而构建的。
kirbyfan64sos

除了可怕的高尔夫球,我唯一用的就是tell app "System Events" to <something>。这有趣的,看看它是如何与这种东西的交易,虽然。@ kirbyfan64sos
艾迪生·克伦普(



6

CJam,12 8 26

r:AAr:B.=0#_W={;;ABe<}{<}?

在线尝试。

(在查看了丹尼斯的答案后,最好使用。=代替.-。)

在所有的情况下,对于像我这样的CJam初学者来说,要保持简短就变得很困难。希望这至少适用于所有情况。


6

C#, 201个 147字节

using System.Linq;class a{static void Main(string[]a){a[0].Take(a[1].Length).TakeWhile((t,i)=>a[1][i]==t).ToList().ForEach(System.Console.Write);}}

我知道这并不十分竞争。我只是想看看它会是什么样子。

编辑:感谢Ash Burlakzenko,Berend和Dennis_E


2
仅获得250字节以下的C#答案具有竞争力。另外,你不能using System.*吗?
2015年

1
.ForEach(x=>Console.Write(x))可以缩短为.ForEach(Console.Write)
Ash Burlaczenko 2015年

1
using System.Collections.Generic;是不必要的。通过删除中的空格来减少一个字节string[] a
Berend

2
1- Contains没有必要。2-您可以通过删除using System;并说出System.Console.Write;3- 来节省一些字节。3-由于此错误,此代码对于输入“ aab”,“ aaab”返回错误的结果(“ a”)IndexOf。我能想到的最短修补程序是使用a[0].Take(a[1].Length)147个字节长:“使用System.Linq; class a {静态void Main(string [] a){a [0] .Take(a [1] .Length).TakeWhile ((c,i)=> a [1] [i] == c).ToList()。ForEach(System.Console.Write);}}“
Dennis_E 2015年

感谢您在休息时发表的评论,我会仔细研究所有这些,尤其是Dennis_E的评论。
Jakotheshadows,2015年


5

Perl 5中,20个 19 18字节

19个字节,再加上1个-E标志,而不是-e

say<>=~/^(.*).* \1/

这是从Digital Traumased答案中无耻复制的。它假定输入是几个单词,两个单词之间没有空格(或第一个单词之前),并且它们之间有一个空格。


更新:

建议使用thisSuitIsBlack-pe,以节省字节(谢谢!):

($_)=/^(.*).* \1/

然后,Luk Storms建议使用-nE以下方法来保存另一个字节(谢谢!):

say/^(.*).* \1/

(我数-E为一个字节而不是标准的-e,但-n还是-p两个。我的印象是,这是SOP在这里。)


1
-M5.010在需要时是免费的”。每个相同的元发布,-pe或者-ne将是1个额外的字节,而不是2 perl -nE 'say/^(.*).* \1/'个。因此得分16个字节。
ThisSuitIsBlackNot

4

Python 3、72

多亏了FryAmTheEggman,节省了31个字节。DSM节省了8条。

r=''
for x,y in zip(input(),input()):
 if x==y:r+=x
 else:break
print(r)

Python程序员将要做zip什么?:D
Beta Decay's

7
@BetaDecay我们的苍蝇将一直开放。
Morgan Thrapp 2015年

你可以把input()S IN的zip并保存ab约束力。
DSM

@DSM Ooo,好点。谢谢!
Morgan Thrapp 2015年

4

Python 3、47

def f(w):[print(end=c[c!=d])for c,d in zip(*w)]

该函数接受w两个单词的列表,并在错误终止之前打印公共前缀。

Python 3的print功能使您可以使用彼此齐平的字符串来打印字符串print(end=c)(感谢Sp3000使用这种较短的语法节省了3个字节)。这会反复从单词中取出两个字母,然后打印第一个字母。索引c[c!=d]产生界外错误,其中c!=d当遇到两个不相等的字母时终止执行。

一个显式的for循环比列表理解长一个char:

def f(w):
 for c,d in zip(*w):print(end=c[c!=d])

哇!我什至没有考虑过使用函数!好东西。+1
扎克·盖茨

现在只看到了这个,但是怎么样print(end=c[c!=d])
Sp3000

1
@ Sp3000哇,我从未将main参数设置print为可选参数,这意味着只能使用end参数来调用它,并且其中可能包含字符串。总的来说,这是一个非常有用的技巧。你应该给个小费。
xnor

3

Javascript ES6,52个字节

f=(a,b)=>[...a].filter((e,i)=>e==b[i]?1:b='').join``

用法:

>> f("global","glossary")
"glo"

不适用于ada,aca...
瑕疵的

哎呀,固定的。字符串不再匹配后,忘记取消过滤。
2015年

1
您无需命名函数,因此f=
可以省去

1
您可以使用地图做得更小(a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join``
Shaun H

2

视网膜,14字节

使用与kirbyfan64sos相同的想法。不幸的是,尽管马丁声称最终的“匹配”模式将具有一种打印捕获组的方式,但尚未实现。否则,(.*).* \1可以将其与2个字节一起用于一些尚不存在的配置字符串选项。

(.*).* \1.*
$1

每行将放入其自己的文件,每个其他文件增加1个字节。或者,在带有-s标志的单个文件中运行。


由于贪婪,等价的正则表达式无法在vim中匹配(非贪婪的正则表达式将匹配最短的子字符串,即空白),您确定它可以工作吗?
2015年

@ Random832尝试使用此正则表达式替换测试器,并选中.NET选项。将操作设置为“替换”,然后将图案放入正确的框中。如果应该有一个,它不会失败。由于贪婪怎么可能失败?那是它起作用的唯一原因。\1确保两个词都以相同的前缀开头。因此,无论多么贪婪(.*)\1都是一样的。
mbomb007

在vim中,它根本拒绝匹配-我认为它为第一个(。*)找到了更长的字符串,然后未能将其与\ 1匹配,然后没有正确地回溯到较短的字符串。
2015年

@ Random832然后,您需要找到其他东西来测试您的正则表达式。
mbomb007

2

K,24个字节

{(+/&\=/(&/#:'x)#'x)#*x}

找到每个字符串的最小长度。((&/#:'x))。将每个字符串修剪到该长度(#'x)。然后比较,涂抹和求和结果序列:

  =/("globaa";"glossa")
1 1 1 0 0 1
  &\=/("globaa";"glossa")
1 1 1 0 0 0
  +/&\=/("globaa";"glossa")
3

最后,从提供的字符串(#*x)的第一个中提取那么多字符。

实际上:

 f: {(+/&\=/(&/#:'x)#'x)#*x};
 f'(("global";"glossary")
    ("department";"depart")
    ("glove";"dove")
    ("aaa";"aaaaa")
    ("identical";"identical")
    ("aca";"aba"))
("glo"
 "depart"
 ()
 "aaa"
 "identical"
 ,"a")

2

Powershell,65个字节

比较字符串,缩小第一个字符串,直到匹配(打印并退出),或者字符串为null并终止循环。

param($a,$b)while($a){if($b-like"$a*"){$a;exit}$a=$a-replace".$"}

2

朱莉娅62字节

f(a,b)=(c="";for(i,j)=zip(a,b) i!=j?break:(c*=string(i))end;c)

取消高尔夫:

function f(a::AbstractString, b::AbstractString)
    # Initialize an output string
    c = ""

    # Iterate over the pairs of characters in a and b,
    # truncated to the shorter of the two lengths
    for (i, j) in zip(a, b)
        if i == j
            # If they match, append to the output string
            c *= string(i)
        else
            # Otherwise stop everything!
            break
        end
    end

    return c
end

由于xnor,解决了一个问题(付出了14字节的巨额费用)!


2

C99,73个字节

main(int c,char *a[]){for(char *x=a[1],*y=a[2];*x==*y++;putchar(*x++));}

此答案类似,但更短且符合规范(从stdin输入)。


Spec并没有说输入必须来自stdin。实际上,这比其他答案长(如果添加)#include<stdio.h>,这对于程序进行编译是必需的。
musarithmia

@AndrewCashner-它不需要在stdin上,但是确实需要输入。另一个答案是硬编码的。另外,gcc抱怨隐式用法,但编译时没有包含即可。
Comintern

没有临时文件的话要短得多:main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));}(59字节)。
Toby Speight

2

MATLAB,50 40字节

定义一个接受2个字符串作为输入,输出到命令窗口的函数

function t(a,b);a(1:find([diff(char(a,b)) 1],1)-1)

此解决方案适用于任何字符串,输出

ans =

   Empty string: 1-by-0

如果没有给出匹配。

可以使用脚本而不是函数(使用局部变量a,b)(-16字节)来打高尔夫球。

所以得到34个字节

a(1:find([diff(char(a,b)) 1],1)-1)

函数样式(似乎是公认的样式)产生

@(a,b)a(1:find([diff(char(a,b)) 1],1)-1)

(感谢@Stewie Griffin)


40个字节:@(a,b)a(1:find([diff(char(a,b)) 1],1)-1)。=)
Stewie Griffin

2

Perl 6,28个字节

我想出了两个基于STDIN的值,它们基于Perl 5的答案。

lines~~/(.*).*' '$0/;say ~$0
lines~~/:s(.*).* $0/;say ~$0

第一个在输入之间恰好需要一个空格,而另一个在输入之间至少需要一个空格字符。


这比我尝试从命令行获取值的第一件事要短得多。

say [~] map ->($a,$b){$a eq$b&&$a||last},[Z] @*ARGS».comb # 58 bytes

甚至是lambda版本:

{[~] map ->($a,$b){$a eq$b&&$a||last},[Z] @_».comb} # 52 bytes

尽管这很容易调整,以使其接受任意数量的输入字符串,但仅需一次敲击。

{[~] map ->@b {([eq] @b)&&@b[0]||last},[Z] @_».comb} # 53 bytes
#          ┗━┛ ┗━━━━━━━┛  ┗━━━┛
my &common-prefix = {[~] map ->@b {([eq] @b)&&@b[0]||last},[Z] @_».comb}

say common-prefix <department depart>; # "depart"
say common-prefix; # ""
say common-prefix <department depart depot deprecated dependant>; # "dep"

# This code does not work directly with a single argument, so you have
# to give it an itemized List or Array, containing a single element.

say common-prefix $('department',); # "department"

# another option would be to replace `@_` with `(@_,)`

2

Japt,27个字节

JaptJa vaScri pt的缩写。口译员

Um$(X,Y)=>$A&&X==VgY ?X:A=P

(字符串进入输入框,如下所示: "global" "glossary"

此代码与以下JS完全等效:

A=10;(U,V)=>U.split``.map((X,Y)=>A&&X==V[Y]?X:A="").join``

我还没有实现匿名功能,这就是$...$它的用途:在切换到JS时,美元符号之间的任何内容都保持不变。添加函数后,此21字节的代码就足够了:

UmXY{A&&X==VgY ?X:A=P

在实现更多功能之后,理想情况下将为18个字节:

UmXY{AxX=VgY ?X:AP

建议欢迎!


因此事实证明,该程序在现代Japt中只有15个字节:

¡A©X¥VgY ?X:A=P

在线尝试!


2

MATL11 9字节

y!=XdYpf)

在线尝试!

(-2字节,感谢Giuseppe)

 y  % implicitly input the two strings, then duplicate the
    %  first one into the stack again
    %  stack: ['department' 'deported' 'department']
 !  % transpose the last string into a column vector
 =  % broadcast equality check - gives back a matrix comparing
    %  every letter in first input with the letters in the second
 Xd % diagonal of the matrix - comparison result of each letter with
    %  only corresponding letter in the other string
    %  stack: ['department' [1; 1; 1; 0; 1; 1; 0; 0;]]
 Yp % cumulative product (so only initial sequence of 1s remains
    %  1s, others become 0)
    %  stack: ['department' [1; 1; 1; 0; 0; 0; 0; 0;]]
 f  %  find the indices of the 1s
 )  % index at those elements so we get those letters out
    % (implicit) convert to string and display

谢谢!这个y想法非常好,我尝试过使用类似Initial的方法,iti而不是1Gw,但是没有想到要使用y
sundar-恢复莫妮卡

1

Clojure / ClojureScript,51

(defn f[[a & b][c & d]](if(= a c)(str a(f b d))""))

非常简单。不幸的是,参数解构周围的空格是必需的(就是这些[a & b]东西)。不是最短的,但我打败了其他一些喜欢夸口其简洁性的语言的答案,因此我将其发布。


1

Python 2,50个字节

for a,b in zip(*input()):print(1/0if a!=b else a),

输入值

输入被视为两个字符串:

"global", "glossary"

输出量

输出是每个字符后跟一个空格;希望这不是问题。但是,如果是这样,我将编辑答案。

g l o 

我很确定这是无效的;规范清楚地给出了输出格式为没有空格的字符串。
lirtosiast

是的,但是输入也是以格式"global" , "glossary"(两个单独的字符串)给出的。字母后面还有多少其他答案?@ThomasKwa
Zach Gates

“采用两个字符串”是OP使用的语言;通常,当提到这样的内容而没有任何限定符时,它指的是我们的默认I / O,这意味着我们可以从命令行中获取一个字符串,从STDIN中获取一个字符串,或者由两个字符串组成的数组,或者跟随这些字符串的其他任何内容规则。
lirtosiast

我认为您对我的回答过于重视。这只是一个有趣的提交,也是我击败内置的最好的尝试。如果OP不喜欢输出格式,那就去吧;我将删除答案。@ThomasKwa
Zach Gates

怎么print(exit()if a!=b else a,end='')样 我不知道这是否行得通,但可能会
Beta Decay

1

TeaScript,16字节20

xf»l¦y[i]?1:b=0)

取每个输入,并用空格分隔。


1

PHP,52字节

并不壮观,但能胜任:

$a=$argv;while($a[1][$i]==$a[2][$i])echo$a[1][$i++];

接受两个命令行参数:

php prefix.php department depart

PHP7可让您保存另一个字节while(($a=$argv)[1][$i]==$a[2][$i])echo$a[1][$i++];-另一个仅PHP7的解决方案(最好我提供@ 50个字节)<?=substr(($a=$argv)[1],0,strspn($a[1]^$a[2],~ÿ));-确保您的编辑器处于ascii模式,重要的~ÿ是不要将其转换为unicode。
Leigh 2015年
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.