Longest common suffix

Longest common suffix is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Write a function to find the longest common suffix string amongst an array of strings.

11l

```F lcs(sa)
I sa.empty
R ‘’
I sa.len == 1
R sa[0]

V min_len = min(sa.map(s -> s.len))

L(i) 1 .. min_len
V p = sa[0][(len)-i]
L(j) 1 .< sa.len
I sa[j][(len)-i] != p
R sa[0][(len)-i+1..]

R sa[0][(len)-min_len..]

print(lcs([‘11Sunday’, ‘2Sunday’]))
print(lcs([‘Sunday’, ‘Monday’, ‘Tuesday’]))
print(lcs([‘Sunday’, ‘Monday’, ‘Tuesday’, ‘day’]))
print(lcs([‘Sondag’, ‘Maandag’, ‘Dinsdag’, ‘Woensdag’]))```
Output:
```Sunday
day
day
dag
```

Action!

```DEFINE PTR="CARD"

BYTE Func Equals(CHAR ARRAY a,b)
BYTE i

IF a(0)#b(0) THEN
RETURN (0)
FI

FOR i=1 TO a(0)
DO
IF a(i)#b(i) THEN
RETURN (0)
FI
OD
RETURN (1)

BYTE FUNC CommonLength(PTR ARRAY texts BYTE count)
CHAR ARRAY t
BYTE i,len

IF count=0 THEN
RETURN (0)
FI

len=255
FOR i=0 TO count-1
DO
t=texts(i)
IF t(0)<len THEN
len=t(0)
FI
OD
RETURN (len)

PROC Suffix(PTR ARRAY texts BYTE count CHAR ARRAY res)
CHAR ARRAY t(100)
CHAR ARRAY tmp
BYTE i,len,found

IF count=1 THEN
SCopy(res,texts(0))
RETURN
FI

len=CommonLength(texts,count)
WHILE len>0
DO
tmp=texts(0)
SCopyS(res,tmp,tmp(0)-len+1,tmp(0))
found=1
FOR i=1 TO count-1
DO
tmp=texts(i)
SCopyS(t,texts(i),tmp(0)-len+1,tmp(0))
IF Equals(res,t)#1 THEN
found=0 EXIT
FI
OD
IF found THEN
RETURN
FI
len==-1
OD
res(0)=0
RETURN

PROC Test(PTR ARRAY texts BYTE count)
BYTE i
CHAR ARRAY res(100)

Suffix(texts,count,res)
Print("lcs(")
IF count>0 THEN
FOR i=0 TO count-1
DO
PrintF("""%S""",texts(i))
IF i<count-1 THEN
Print(",")
FI
OD
FI
PrintF(")=""%S""%E",res)
RETURN

PROC Main()
CHAR ARRAY
t1="Sunday", t2="Monday", t3="Tuesday", t4="Wednesday",
t5="Thursday", t6="Friday", t7="Saturday",
t8="throne", t9="throne", t10="dungeon", t11="",
t12="prefix", t13="suffix"
PTR ARRAY texts(20)

texts(0)=t1 texts(1)=t2 texts(2)=t3
texts(3)=t4 texts(4)=t5 texts(5)=t6
texts(6)=t7
Test(texts,7)

texts(0)=t8 texts(1)=t9
Test(texts,2)

texts(0)=t8 texts(1)=t10
Test(texts,2)

texts(0)=t8 texts(1)=t11 texts(2)=t9
Test(texts,3)

texts(0)=t10
Test(texts,1)

texts(0)=t11
Test(texts,1)

Test(texts,0)

texts(0)=t12 texts(1)=t13
Test(texts,2)
RETURN```
Output:
```lcs("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")="day"
lcs("throne","throne")="throne"
lcs("throne","dungeon")=""
lcs("throne","","throne")=""
lcs("dungeon")="dungeon"
lcs("")=""
lcs()=""
lcs("prefix","suffix")="fix"
```

```with Ada.Strings.Unbounded;

procedure Longest_Common_Suffix is

subtype Ustring is Unbounded_String;

function "+"(S : String) return Ustring
renames To_Unbounded_String;

type String_List is array (Positive range <>) of Ustring;

function Longest_Suffix (List : String_List) return Ustring is
Suffix : Ustring := List (List'First);
begin
for A in List'First + 1 .. List'Last loop
declare
Word  : Ustring renames List (A);
Found : Boolean := False;
Len   : constant Natural :=
Natural'Min (Length (Suffix), Length (Word));
begin
for P in reverse 1 .. Len loop
if Tail (Suffix, P) = Tail (Word, P) then
Suffix := Tail (Word, P);
Found := True;
exit;
end if;
end loop;
Suffix := +"";
end if;
end;
end loop;
return Suffix;
end Longest_Suffix;

procedure Put (List : String_List) is
begin
Put ("[");
for S of List loop
Put ("'"); Put (S); Put ("' ");
end loop;
Put ("]");
end Put;

procedure Test (List : String_List) is
begin
Put (List); Put (" -> '");
Put (Longest_Suffix (List));
Put ("'");
New_Line;
end Test;

Case_1 : constant String_List := (+"baabababc", +"baabc", +"bbbabc");
Case_2 : constant String_List := (+"baabababc", +"baabc", +"bbbazc");
Case_3 : Constant String_List := (+"Sunday", +"Monday", +"Tuesday",
+"Wednesday", +"Thursday", +"Friday",
+"Saturday");
Case_4 : constant String_List := (+"longest", +"common", +"suffix");
Case_5 : constant String_List := (1 => +"suffix");
Case_6 : Constant String_List := (1 => +"");
begin
Test (Case_1);
Test (Case_2);
Test (Case_3);
Test (Case_4);
Test (Case_5);
Test (Case_6);
end Longest_Common_Suffix;
```
Output:
```['baabababc' 'baabc' 'bbbabc' ] -> 'abc'
['baabababc' 'baabc' 'bbbazc' ] -> 'c'
['Sunday' 'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday' 'Saturday' ] -> 'day'
['longest' 'common' 'suffix' ] -> ''
['suffix' ] -> 'suffix'
['' ] -> ''
```

ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

Based on the Algol 68 sample for the Longest Common Prefix task.

```# find the longest common suffix of two strings #
PRIO COMMONSUFFIX = 1;
OP   COMMONSUFFIX = ( STRING a, b )STRING:
BEGIN
INT a pos := UPB a; INT a min = LWB a;
INT b pos := UPB b; INT b min = LWB b;
WHILE
IF a pos < a min OR b pos < b min THEN FALSE
ELSE a[ a pos ] = b[ b pos ]
FI
DO
a pos -:= 1; b pos -:= 1
OD;
a[ a pos + 1 : UPB a ]
END # COMMONSUFFIX # ;
# get the length of a string #
OP  LEN = ( STRING a )INT: ( UPB a + 1 ) - LWB a;
# find the longest common suffix of an array of STRINGs #
OP  LONGESTSUFFIX = ( []STRING list )STRING:
IF  UPB list < LWB list
THEN
# no elements #
""
ELIF UPB list = LWB list
THEN
# only one element #
list[ LWB list ]
ELSE
# more than one element #
STRING suffix := list[ LWB list ] COMMONSUFFIX list[ 1 + LWB list ];
FOR pos FROM 2 + LWB list TO UPB list WHILE suffix /= "" DO
STRING next suffix := list[ pos ] COMMONSUFFIX suffix;
IF LEN next suffix < LEN suffix
THEN
# this element has a smaller common suffix #
suffix := next suffix
FI
OD;
suffix
FI ;
# test the LONGESTSUFFIX operator #
PROC test suffix = ( []STRING list, STRING expected result )VOID:
BEGIN
STRING suffix = LONGESTSUFFIX list;
print( ( "longest common suffix of (" ) );
FOR pos FROM LWB list TO UPB list DO print( ( " """, list[ pos ], """" ) ) OD;
print( ( " ) is: """, suffix, """ "
, IF suffix = expected result THEN "as expected" ELSE "NOT AS EXPECTED" FI
, newline
)
)
END # test suffix # ;
[ 1 : 0 ]STRING empty list; # for recent versions of Algol 68G, can't just put "()" for an empty list #
BEGIN
test suffix( ( "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ), "day" );
test suffix( ( "throne", "throne" ), "throne" );
test suffix( ( "throne", "dungeon" ), "" );
test suffix( ( "throne", "", "throne" ), "" );
test suffix( ( "cheese" ), "cheese" );
test suffix( ( "" ), "" );
test suffix( empty list, "" );
test suffix( ( "prefix", "suffix" ), "fix" );
test suffix( ( "send", "lend" ), "end" )
END```
Output:
```longest common suffix of ( "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" ) is: "day" as expected
longest common suffix of ( "throne" "throne" ) is: "throne" as expected
longest common suffix of ( "throne" "dungeon" ) is: "" as expected
longest common suffix of ( "throne" "" "throne" ) is: "" as expected
longest common suffix of ( "cheese" ) is: "cheese" as expected
longest common suffix of ( "" ) is: "" as expected
longest common suffix of ( ) is: "" as expected
longest common suffix of ( "prefix" "suffix" ) is: "fix" as expected
longest common suffix of ( "send" "lend" ) is: "end" as expected
```

APL

Works with: Dyalog APL
```lcs ← ⌽+/∘(∧\)∘⊃∘(∧/2=/(⌊/≢¨)↑¨⌽¨)↑⌽∘⊃
```
Output:
```      lcs 'baabababc' 'baabc' 'bbbabc'
abc
lcs 'baabababc' 'baabc' 'bbbazc'
c
lcs 'Sunday' 'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday' 'Saturday'
day
lcs 'longest' 'common' 'suffix'

lcs ,⊂''

```

AppleScript

Procedural

The simplest solution in AppleScript seems to be to reverse the strings, apply the AppleScriptObjC solution for the Longest common prefix task, and reverse the result.

```use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"

on longestCommonSuffix(textList)
-- Eliminate any non-texts from the input.
if (textList's class is record) then return ""
set textList to (textList as list)'s text
if (textList is {}) then return ""

set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
repeat with i from 1 to (count textList)
set item i of textList to (reverse of characters of item i of textList) as text
end repeat
set lcs to (reverse of characters of longestCommonPrefix(textList)) as text
set AppleScript's text item delimiters to astid

return lcs
end longestCommonSuffix

on longestCommonPrefix(textList)
-- Eliminate any non-texts from the input.
if (textList's class is record) then return ""
set textList to (textList as list)'s text
if (textList is {}) then return ""

-- Convert the AppleScript list to an NSArray of NSStrings.
set stringArray to current application's class "NSArray"'s arrayWithArray:(textList)

-- Compare the strings case-insensitively using a built-in NSString method.
set lcp to stringArray's firstObject()
repeat with i from 2 to (count stringArray)
set lcp to (lcp's commonPrefixWithString:(item i of stringArray) options:(current application's NSCaseInsensitiveSearch))
if (lcp's |length|() is 0) then exit repeat
end repeat

-- Return the NSString result as AppleScript text.
return lcp as text
end longestCommonPrefix

-- Tests and results:
longestCommonSuffix({"throne", "sousaphone"}) --> "one"
longestCommonSuffix({"prefix", "suffix"}) --> "fix"
longestCommonSuffix({"remark", "spark", "aardvark"}) --> "ark"
longestCommonSuffix({"ectoplasm", "banana"}) --> ""
```

Functional

and for more productivity, and higher re-use of library functions, we can write a functional definition (rather than a procedure):

```------------------- LONGEST COMMON SUFFIX ------------------

-- longestCommonSuffix :: [String] -> String
on longestCommonSuffix(xs)
if 1 < length of xs then
reverse of map(my fst, ¬
takeWhile(my allSame, ¬
transpose(map(my |reverse|, xs)))) as text
else
xs as text
end if
end longestCommonSuffix

---------------------------- TESTS --------------------------
on run
script test
on |λ|(s)
set xs to words of s
showList(xs) & " -> '" & longestCommonSuffix(xs) & "'"
end |λ|
end script

unlines(map(test, {¬
"throne sousaphone tone", ¬
"prefix suffix infix", ¬
"remark spark aardvark lark", ¬
"ectoplasm banana brick"}))
end run

--------------------- GENERIC FUNCTIONS --------------------

-- all :: (a -> Bool) -> [a] -> Bool
on all(p, xs)
-- True if p holds for every value in xs
tell mReturn(p)
set lng to length of xs
repeat with i from 1 to lng
if not |λ|(item i of xs, i, xs) then return false
end repeat
true
end tell
end all

-- allSame :: [a] -> Bool
on allSame(xs)
if 2 > length of xs then
true
else
script p
property h : item 1 of xs
on |λ|(x)
h = x
end |λ|
end script
all(p, rest of xs)
end if
end allSame

-- comparing :: (a -> b) -> (a -> a -> Ordering)
on comparing(f)
script
on |λ|(a, b)
tell mReturn(f)
set fa to |λ|(a)
set fb to |λ|(b)
if fa < fb then
-1
else if fa > fb then
1
else
0
end if
end tell
end |λ|
end script
end comparing

-- concatMap :: (a -> [b]) -> [a] -> [b]
on concatMap(f, xs)
set lng to length of xs
set acc to {}
tell mReturn(f)
repeat with i from 1 to lng
set acc to acc & (|λ|(item i of xs, i, xs))
end repeat
end tell
return acc
end concatMap

-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl

-- fst :: (a, b) -> a
on fst(tpl)
if class of tpl is record then
|1| of tpl
else
item 1 of tpl
end if
end fst

-- intercalate :: String -> [String] -> String
on intercalate(delim, xs)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, delim}
set str to xs as text
set my text item delimiters to dlm
str
end intercalate

-- justifyLeft :: Int -> Char -> String -> String
on justifyLeft(n, cFiller)
script
on |λ|(strText)
if n > length of strText then
text 1 thru n of (strText & replicate(n, cFiller))
else
strText
end if
end |λ|
end script
end justifyLeft

-- length :: [a] -> Int
on |length|(xs)
set c to class of xs
if list is c or string is c then
length of xs
else
(2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
end if
end |length|

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of xs.
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map

-- maximumBy :: (a -> a -> Ordering) -> [a] -> a
on maximumBy(f, xs)
set cmp to mReturn(f)
script max
on |λ|(a, b)
if a is missing value or cmp's |λ|(a, b) < 0 then
b
else
a
end if
end |λ|
end script

foldl(max, missing value, xs)
end maximumBy

-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min

-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn

-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary
-- assembly of a target length
-- replicate :: Int -> a -> [a]
on replicate(n, a)
set out to {}
if 1 > n then return out
set dbl to {a}

repeat while (1 < n)
if 0 < (n mod 2) then set out to out & dbl
set n to (n div 2)
set dbl to (dbl & dbl)
end repeat
return out & dbl
end replicate

-- reverse :: [a] -> [a]
on |reverse|(xs)
if class of xs is text then
(reverse of characters of xs) as text
else
reverse of xs
end if
end |reverse|

-- showList :: [a] -> String
on showList(xs)
script show
on |λ|(x)
if text is class of x then
"'" & x & "'"
else
x as text
end if
end |λ|
end script
if {} ≠ xs then
"[" & intercalate(", ", map(show, xs)) & "]"
else
"[]"
end if
end showList

-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
set c to class of xs
if list is c then
if 0 < n then
items 1 thru min(n, length of xs) of xs
else
{}
end if
else if string is c then
if 0 < n then
text 1 thru min(n, length of xs) of xs
else
""
end if
else if script is c then
set ys to {}
repeat with i from 1 to n
set v to |λ|() of xs
if missing value is v then
return ys
else
set end of ys to v
end if
end repeat
return ys
else
missing value
end if
end take

-- takeWhile :: (a -> Bool) -> [a] -> [a]
-- takeWhile :: (Char -> Bool) -> String -> String
on takeWhile(p, xs)
if script is class of xs then
takeWhileGen(p, xs)
else
tell mReturn(p)
repeat with i from 1 to length of xs
if not |λ|(item i of xs) then ¬
return take(i - 1, xs)
end repeat
end tell
return xs
end if
end takeWhile

-- transpose :: [[a]] -> [[a]]
on transpose(rows)
set w to length of maximumBy(comparing(|length|), rows)
set paddedRows to map(justifyLeft(w, "x"), rows)

script cols
on |λ|(_, iCol)
script cell
on |λ|(row)
item iCol of row
end |λ|
end script
end |λ|
end script

map(cols, item 1 of rows)
end transpose

-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set str to xs as text
set my text item delimiters to dlm
str
end unlines
```
Output:
```['throne', 'sousaphone', 'tone'] -> 'one'
['prefix', 'suffix', 'infix'] -> 'fix'
['remark', 'spark', 'aardvark', 'lark'] -> 'ark'
['ectoplasm', 'banana', 'brick'] -> ''```

Arturo

```lcs: function [l][
ret: ""
idx: 0

lst: map l => reverse

while [true] [
thisLetter: ""
loop lst 'word [
if idx=size word -> return reverse ret
if thisLetter="" -> thisLetter: get split word idx
if thisLetter<>get split word idx -> return reverse ret
]
ret: ret ++ thisLetter
idx: idx + 1
]
]

print lcs ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"]
print lcs ["throne" "throne"]
print lcs ["throne" "dungeon"]
print lcs ["cheese"]
print lcs ["prefix" "suffix"]
```
Output:
```day
throne

cheese
fix```

AutoHotkey

```Longest_common_suffix(data){
for num, v in StrSplit(data.1)
for i, word in data
if (SubStr(word, 1-num) <> SubStr(data.1, 1-num))
return num=1 ? "" : SubStr(word, 2-num)
return SubStr(word, 1-num)
}
```

Examples:

```MsgBox % ""
. "`n" Longest_common_suffix(["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"])
. "`n" Longest_common_suffix(["throne", "throne"])
. "`n" Longest_common_suffix(["throne", "dungeon"])
. "`n" Longest_common_suffix(["throne", "", "throne"])
. "`n" Longest_common_suffix(["cheese"])
. "`n" Longest_common_suffix([""])
. "`n" Longest_common_suffix(["prefix", "suffix"])
. "`n" Longest_common_suffix(["bar", "foobar"])
return
```
Output:
```day
throne

cheese

fix
bar```

AWK

```# syntax: GAWK -f LONGEST_COMMON_SUFFIX.AWK
BEGIN {
arr1[++n1] = "AAbcd,Abcd,abcd,bcd"
arr1[++n1] = "11Sunday,2Sunday"
arr1[++n1] = "Sunday,Monday"
arr1[++n1] = "Sunday,Monday,day"
arr1[++n1] = "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday"
arr1[++n1] = "crucifix,infix,prefix,suffix"
arr1[++n1] = "identical,identical"
arr1[++n1] = ","
arr1[++n1] = "this,has,nothing,in,common"
for (i=1; i<=n1; i++) {
n2 = split(arr1[i],arr2,",")
min_wid = 999
for (j=1; j<=n2; j++) {
leng = length(arr2[j])
if (min_wid > leng) {
min_wid = leng
min_col = j
}
}
cols = 0
for (j=1; j<=min_wid; j++) {
delete arr3
for (k=1; k<n2; k++) {
arr3[substr(arr2[k],length(arr2[k])+1-j)] = ""
arr3[substr(arr2[k+1],length(arr2[k+1])+1-j)] = ""
}
if (length(arr3) == 1) {
cols++
}
}
printf("'%s' : '%s'\n",arr1[i],(cols == 0) ? "" : substr(arr2[min_col],length(arr2[min_col])+1-cols))
}
exit(0)
}
```
Output:
```'AAbcd,Abcd,abcd,bcd' : 'bcd'
'11Sunday,2Sunday' : 'Sunday'
'Sunday,Monday' : 'nday'
'Sunday,Monday,day' : 'day'
'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday' : 'day'
'crucifix,infix,prefix,suffix' : 'fix'
'identical,identical' : 'identical'
',' : ''
'this,has,nothing,in,common' : ''
```

BaCon

```FUNCTION Common_Suffix\$(data\$)

LOCAL x, size
LOCAL delim\$

REPEAT
delim\$ = ""
INCR size

FOR x = 1 TO AMOUNT(data\$)
delim\$ = APPEND\$(delim\$, 0, RIGHT\$(TOKEN\$(data\$, x), size))
NEXT
UNTIL AMOUNT(UNIQ\$(delim\$)) <> 1

RETURN RIGHT\$(TOKEN\$(data\$, 1), size-1)

ENDFUNCTION

PRINT "The common suffix is: '", Common_Suffix\$("baabababc baabc bbbabc"), "'"
PRINT "The common suffix is: '", Common_Suffix\$("Monday Tuesday Wednesday Thursday Friday Saturday Sunday"), "'"
PRINT "The common suffix is: '", Common_Suffix\$("longest common suffix"), "'"
PRINT "The common suffix is: '", Common_Suffix\$("prefix suffix"), "'"
PRINT "The common suffix is: '", Common_Suffix\$(""), "'"```
Output:
```The common suffix is: 'abc'
The common suffix is: 'day'
The common suffix is: ''
The common suffix is: 'fix'
The common suffix is: ''```

C

```#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node_t {
char *elem;
int length;
struct node_t *next;
} node;

node *make_node(char *s) {
node *t = malloc(sizeof(node));
t->elem = s;
t->length = strlen(s);
t->next = NULL;
return t;
}

void append_node(node *head, node *elem) {
}
}

void print_node(node *n) {
putc('[', stdout);
while (n != NULL) {
printf("`%s` ", n->elem);
n = n->next;
}
putc(']', stdout);
}

char *lcs(node *list) {
int minLen = INT_MAX;
int i;

char *res;
node *ptr;

if (list == NULL) {
return "";
}
if (list->next == NULL) {
return list->elem;
}

for (ptr = list; ptr != NULL; ptr = ptr->next) {
minLen = min(minLen, ptr->length);
}
if (minLen == 0) {
return "";
}

res = "";
for (i = 1; i < minLen; i++) {
char *suffix = &list->elem[list->length - i];

for (ptr = list->next; ptr != NULL; ptr = ptr->next) {
char *e = &ptr->elem[ptr->length - i];
if (strcmp(suffix, e) != 0) {
return res;
}
}

res = suffix;
}

return res;
}

void test(node *n) {
print_node(n);
printf(" -> `%s`\n", lcs(n));
}

void case1() {
node *n = make_node("baabababc");
append_node(n, make_node("baabc"));
append_node(n, make_node("bbbabc"));
test(n);
}

void case2() {
node *n = make_node("baabababc");
append_node(n, make_node("baabc"));
append_node(n, make_node("bbbazc"));
test(n);
}

void case3() {
node *n = make_node("Sunday");
append_node(n, make_node("Monday"));
append_node(n, make_node("Tuesday"));
append_node(n, make_node("Wednesday"));
append_node(n, make_node("Thursday"));
append_node(n, make_node("Friday"));
append_node(n, make_node("Saturday"));
test(n);
}

void case4() {
node *n = make_node("longest");
append_node(n, make_node("common"));
append_node(n, make_node("suffix"));
test(n);
}

void case5() {
node *n = make_node("suffix");
test(n);
}

void case6() {
node *n = make_node("");
test(n);
}

int main() {
case1();
case2();
case3();
case4();
case5();
case6();
return 0;
}
```
Output:
```[`baabababc` `baabc` `bbbabc` ] -> `abc`
[`baabababc` `baabc` `bbbazc` ] -> `c`
[`Sunday` `Monday` `Tuesday` `Wednesday` `Thursday` `Friday` `Saturday` ] -> `day`
[`longest` `common` `suffix` ] -> ``
[`suffix` ] -> `suffix`
[`` ] -> `````

C++

```#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

std::string lcs(const std::vector<std::string>& strs) {
std::vector<std::string::const_reverse_iterator> backs;
std::string s;

if (strs.size() == 0) return "";
if (strs.size() == 1) return strs[0];

for (auto& str : strs) backs.push_back(str.crbegin());

while (backs[0] != strs[0].crend()) {
char ch = *backs[0]++;
for (std::size_t i = 1; i<strs.size(); i++) {
if (backs[i] == strs[i].crend()) goto done;
if (*backs[i] != ch) goto done;
backs[i]++;
}
s.push_back(ch);
}

done:
reverse(s.begin(), s.end());
return s;
}

void test(const std::vector<std::string>& strs) {
std::cout << "[";
for (std::size_t i = 0; i<strs.size(); i++) {
std::cout << '"' << strs[i] << '"';
if (i != strs.size()-1) std::cout << ", ";
}
std::cout << "] -> `" << lcs(strs) << "`\n";
}

int main() {
std::vector<std::string> t1 = {"baabababc", "baabc", "bbabc"};
std::vector<std::string> t2 = {"baabababc", "baabc", "bbazc"};
std::vector<std::string> t3 =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Friday", "Saturday"};
std::vector<std::string> t4 = {"longest", "common", "suffix"};
std::vector<std::string> t5 = {""};
std::vector<std::string> t6 = {};
std::vector<std::string> t7 = {"foo", "foo", "foo", "foo"};

std::vector<std::vector<std::string>> tests = {t1,t2,t3,t4,t5,t6,t7};

for (auto t : tests) test(t);
return 0;
}
```
Output:
```["baabababc", "baabc", "bbabc"] -> `abc`
["baabababc", "baabc", "bbazc"] -> `c`
["Sunday", "Monday", "Tuesday", "Wednesday", "Friday", "Saturday"] -> `day`
["longest", "common", "suffix"] -> ``
[""] -> ``
[] -> ``
["foo", "foo", "foo", "foo"] -> `foo````

Cowgol

```include "cowgol.coh";
include "strings.coh";

sub lcs(arr: [[uint8]], len: intptr): (s: [uint8]) is
if len == 0 then
s := "";
return;
elseif len == 1 then
s := [arr];
return;
end if;

s := [arr];
var slen := StrLen(s);
s := s + slen;

arr := @next arr;
len := len - 1;

while len > 0 and slen > 0 loop
var c := [arr];
var clen := StrLen(c);
c := c + clen;

if clen > slen then
clen := slen;
end if;

while clen > 0 and [c] == [s] loop
c := @prev c;
s := @prev s;
clen := clen - 1;
end loop;

slen := StrLen(s);
s := s + slen;

arr := @next arr;
len := len - 1;
end loop;

s := s - slen + 1;
end sub;

sub test(arr: [[uint8]], len: intptr) is
var s := arr;
var l := len;
print_char('[');
while l > 0 loop
print_char('"');
print([s]);
print_char('"');
s := @next s;
l := l - 1;
if l > 0 then
print(", ");
end if;
end loop;
print("] -> `");
print(lcs(arr, len));
print("`\n");
end sub;

var test1: [uint8][] := {"baabababc", "baabc", "bbbabc"};
var test2: [uint8][] := {"baabababc", "baabc", "bbbazc"};
var test3: [uint8][] :=
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"};
var test4: [uint8][] := {"longest", "common", "suffix"};
var test5: [uint8][] := {""};
var test6: [uint8][] := {};

test(&test1[0], @sizeof test1);
test(&test2[0], @sizeof test2);
test(&test3[0], @sizeof test3);
test(&test4[0], @sizeof test4);
test(&test5[0], @sizeof test5);
test(&test6[0], @sizeof test6);```
Output:
```["baabababc", "baabc", "bbbabc"] -> `abc`
["baabababc", "baabc", "bbbazc"] -> `c`
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] -> `day`
["longest", "common", "suffix"] -> ``
[""] -> ``
[] -> `````

D

Translation of: Kotlin
```import std.algorithm;
import std.stdio;

string lcs(string[] a) {
auto le = a.length;
if (le == 0) {
return "";
}
if (le == 1) {
return a[0];
}
auto le0 = a[0].length;
auto minLen = a.map!"a.length".reduce!"min(a,b)";
if (minLen == 0) {
return "";
}
auto res = "";
foreach (i; 1..minLen) {
auto suffix = a[0][le0 - i .. \$];
foreach (e; a[1..\$]) {
if (!e.endsWith(suffix)) {
return res;
}
}
res = suffix;
}
return "";
}

void main() {
auto tests = [
["baabababc", "baabc", "bbbabc"],
["baabababc", "baabc", "bbbazc"],
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
["longest", "common", "suffix"],
["suffix"],
[""]
];
foreach (test; tests) {
writeln(test, " -> `", lcs(test), '`');
}
}
```
Output:
```["baabababc", "baabc", "bbbabc"] -> `abc`
["baabababc", "baabc", "bbbazc"] -> `c`
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] -> `day`
["longest", "common", "suffix"] -> ``
["suffix"] -> `suffix`
[""] -> `````

Delphi

Library: Types
Translation of: Ring
```program Longest_common_suffix;

{\$APPTYPE CONSOLE}

uses
System.SysUtils,
Types;

type
TStringDynArrayHelper = record helper for TStringDynArray
private
class function Compare(const s: string; a: TStringDynArray; subSize: integer):
Boolean;
public
function Reverse(value: string): string;
function LongestSuffix: string;
function Join(const sep: char): string;
end;

{ TStringDynArrayHelper }

class function TStringDynArrayHelper.Compare(const s: string; a: TStringDynArray;
subSize: integer): Boolean;
var
i: Integer;
begin
for i := 0 to High(a) do
if s <> a[i].Substring(0, subSize) then
exit(False);
Result := True;
end;

function TStringDynArrayHelper.Join(const sep: char): string;
begin
Result := string.Join(sep, self);
end;

function TStringDynArrayHelper.LongestSuffix: string;
var
ALength: Integer;
i, lenMin, longest: Integer;
ref: string;
begin
ALength := Length(self);

// Empty list
if ALength = 0 then
exit('');

lenMin := MaxInt;
for i := 0 to ALength - 1 do
begin
// One string is empty
if self[i].IsEmpty then
exit('');

self[i] := Reverse(self[i]);

// Get the minimum length of string
if lenMin > self[i].Length then
lenMin := self[i].Length;
end;

longest := -1;
repeat
inc(longest);
ref := self[0].Substring(0, longest + 1);
until not compare(ref, Self, longest + 1) or (longest >= lenMin);

Result := self[0].Substring(0, longest);
Result := reverse(Result);
end;

function TStringDynArrayHelper.Reverse(value: string): string;
var
ALength: Integer;
i: Integer;
c: Char;
begin
ALength := value.Length;
Result := value;

if ALength < 2 then
exit;

for i := 1 to ALength div 2 do
begin
c := Result[i];
Result[i] := Result[ALength - i + 1];
Result[ALength - i + 1] := c;
end;
end;

var
List: TStringDynArray;

begin
List := ['baabababc', 'baabc', 'bbbabc'];

Writeln('Input:');
Writeln(List.Join(#10), #10);
Writeln('Longest common suffix = ', List.LongestSuffix);

end.
```
Output:
```Input:
baabababc
baabc
bbbabc

Longest common suffix = abc
```

EasyLang

```func\$ right s\$ i .
return substr s\$ (len s\$ - i + 1) i
.
func\$ lcs list\$[] .
if len list\$[] = 0
return ""
.
ref\$ = list\$[1]
for s\$ in list\$[]
if len s\$ < len ref\$
ref\$ = s\$
.
.
for i = 1 to len ref\$
sub\$ = right ref\$ i
for s\$ in list\$[]
if right s\$ i <> sub\$
return right ref\$ (i - 1)
.
.
.
return ref\$
.
print lcs [ "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" ]
print lcs [ "throne" "throne" ]
print lcs [ "throne" "dungeon" ]
print lcs [ "cheese" ]
print lcs [ "prefix" "suffix" ]```
Output:
```day
throne

cheese
fix
```

Factor

Works with: Factor version 0.99 2020-07-03
```USING: accessors grouping kernel prettyprint sequences
sequences.extras ;

! Like take-while, but for matrices and works from the rear.
: take-col-while-last ( ... matrix quot: ( ... col -- ... ? ) -- ... new-matrix )
[ [ <reversed> ] map flip ] dip take-while ; inline

: lcs ( seq -- lcs )
dup first swap [ all-equal? ] take-col-while-last to>> tail* ;

{ "baabababc" "baabc" "bbbabc" } lcs .
{ "baabababc" "baabc" "bbbazc" } lcs .
{ "" } lcs .
```
Output:
```"abc"
"c"
""
```

FreeBASIC

Translation of: Ring
```Dim As String pre(1 To ...) = {"baabababc","baabc","bbbabc"}
Dim As Integer longitud = Ubound(pre)
Dim As Integer lenList(longitud)
Dim As Integer n, m, longest
Dim As String temp

Function rever(Byval text As String) As String
Dim As String text2 = text
Dim As Integer x, lt = Len(text)
For x = 0 To lt Shr 1 - 1
Swap text2[x], text2[lt - x - 1]
Next x
Return text2
End Function

Print "There are"; longitud; " words in the list:  ";
For n = 1 To longitud
Print pre(n); "  ";
temp = pre(n)
pre(n) = rever(temp)
lenList(n) = Len(pre(n))
Next n

For m = 1 To lenList(1)
Dim As String sub1 = Mid(pre(1),1,m)
Dim As String sub2 = Mid(pre(2),1,m)
Dim As String sub3 = Mid(pre(3),1,m)
If sub1 = sub2 And sub2 = sub3 Then longest = m
Next m

Dim As String longPrefix = Mid(pre(1),1,longest)
longPrefix = rever(longPrefix)

Print !"\n\nThe longest common suffix is:  "; longPrefix
Sleep```
Output:
```There are 3 words in the list:  baabababc  baabc  bbbabc

The longest common suffix is:  abc```

Go

Translation of: Wren
```package main

import (
"fmt"
"strings"
)

func lcs(a []string) string {
le := len(a)
if le == 0 {
return ""
}
if le == 1 {
return a[0]
}
le0 := len(a[0])
minLen := le0
for i := 1; i < le; i++ {
if len(a[i]) < minLen {
minLen = len(a[i])
}
}
if minLen == 0 {
return ""
}
res := ""
a1 := a[1:]
for i := 1; i <= minLen; i++ {
suffix := a[0][le0-i:]
for _, e := range a1 {
if !strings.HasSuffix(e, suffix) {
return res
}
}
res = suffix
}
return res
}

func main() {
tests := [][]string{
{"baabababc", "baabc", "bbbabc"},
{"baabababc", "baabc", "bbbazc"},
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
{"longest", "common", "suffix"},
{"suffix"},
{""},
}
for _, test := range tests {
fmt.Printf("%v -> \"%s\"\n", test, lcs(test))
}
}
```
Output:
```[baabababc baabc bbbabc] -> "abc"
[baabababc baabc bbbazc] -> "c"
[Sunday Monday Tuesday Wednesday Thursday Friday Saturday] -> "day"
[longest common suffix] -> ""
[suffix] -> "suffix"
[] -> ""
```

This task clearly needs a little more work to bring it up to the usual standard – it's rather underspecified, and bereft of test samples – but one response, for the moment, might be something like:

```import Data.List (transpose)

longestCommonSuffix :: [String] -> String
longestCommonSuffix =
foldr (flip (<>) . return . head) [] .
takeWhile (all =<< (==) . head) . transpose . fmap reverse

main :: IO ()
main =
mapM_
(putStrLn . longestCommonSuffix)
[ [ "Sunday"
, "Monday"
, "Tuesday"
, "Wednesday"
, "Thursday"
, "Friday"
, "Saturday"
]
, [ "Sondag"
, "Maandag"
, "Dinsdag"
, "Woensdag"
, "Donderdag"
, "Vrydag"
, "Saterdag"
, "dag"
]
]
```
Output:
```day
dag```

J

```lcs =: [: |. [: ({. #~ [: *./\ [: *./ 2 =/\ ]) >@(|. each)

test1 =: 'baabababc';'baabc';'bbabc'
test2 =: 'baabababc';'baabc';'bbazc'
test3 =: 'Sunday';'Monday';'Tuesday';'Wednesday';'Friday';'Saturday'
test4 =: 'longest';'common';'suffix'
tests =: test1;test2;test3;<test4
echo@((1{":),' -> ', 1{":@<@lcs) each tests
exit''
```
Output:
```│baabababc│baabc│bbabc│ -> │abc│
│baabababc│baabc│bbazc│ -> │c│
│Sunday│Monday│Tuesday│Wednesday│Friday│Saturday│ -> │day│
│longest│common│suffix│ -> ││```

Java

Translation of: Kotlin
```import java.util.List;

public class App {
private static String lcs(List<String> a) {
var le = a.size();
if (le == 0) {
return "";
}
if (le == 1) {
return a.get(0);
}
var le0 = a.get(0).length();
var minLen = le0;
for (int i = 1; i < le; i++) {
if (a.get(i).length() < minLen) {
minLen = a.get(i).length();
}
}
if (minLen == 0) {
return "";
}
var res = "";
var a1 = a.subList(1, a.size());
for (int i = 1; i < minLen; i++) {
var suffix = a.get(0).substring(le0 - i);
for (String e : a1) {
if (!e.endsWith(suffix)) {
return res;
}
}
res = suffix;
}
return "";
}

public static void main(String[] args) {
var tests = List.of(
List.of("baabababc", "baabc", "bbbabc"),
List.of("baabababc", "baabc", "bbbazc"),
List.of("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"),
List.of("longest", "common", "suffix"),
List.of("suffix"),
List.of("")
);
for (List<String> test : tests) {
System.out.printf("%s -> `%s`\n", test, lcs(test));
}
}
}
```
Output:
```[baabababc, baabc, bbbabc] -> `abc`
[baabababc, baabc, bbbazc] -> `c`
[Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] -> `day`
[longest, common, suffix] -> ``
[suffix] -> `suffix`
[] -> `````

JavaScript

```(() => {
'use strict';

// --------------- LONGEST COMMON SUFFIX ---------------

// longestCommonSuffix :: [String] -> String
const longestCommonSuffix = xs => (
1 < xs.length ? (
takeWhile(allSame)(
transpose(xs.map(reverse))
).map(fst).reverse()
) : xs
).join('');

// ----------------------- TEST ------------------------
const main = () =>
fTable('Longest common suffix:\n')(unwords)(
quoted("'")
)(longestCommonSuffix)([
'throne saxophone tone',
'prefix suffix infix',
'remark spark aardvark lark',
'ectoplasm banana brick'
].map(words))

// ----------------- GENERIC FUNCTIONS -----------------

// allSame :: [a] -> Bool
const allSame = xs =>
2 > xs.length || (
h => xs.slice(1).every(x => h === x)
)(xs[0]);

// fst :: (a, b) -> a
const fst = tpl =>
// First member of a pair.
tpl[0];

// fTable :: String -> (a -> String) ->
// (b -> String) -> (a -> b) -> [a] -> String
const fTable = s =>
// Heading -> x display function ->
//           fx display function ->
//    f -> values -> tabular string
xShow => fxShow => f => xs => {
const
ys = xs.map(xShow),
w = Math.max(...ys.map(length));
return s + '\n' + zipWith(
a => b => a.padStart(w, ' ') + ' -> ' + b
)(ys)(
xs.map(x => fxShow(f(x)))
).join('\n');
};

// length :: [a] -> Int
const length = xs =>
// Returns Infinity over objects without finite
// length. This enables zip and zipWith to choose
// the shorter argument when one is non-finite,
// like cycle, repeat etc
'GeneratorFunction' !== xs.constructor
.constructor.name ? xs.length : Infinity;

// map :: (a -> b) -> [a] -> [b]
const map = f =>
// The list obtained by applying f
// to each element of xs.
// (The image of xs under f).
xs => [...xs].map(f);

// reverse :: [a] -> [a]
const reverse = xs =>
'string' !== typeof xs ? (
xs.slice(0).reverse()
) : xs.split('').reverse().join('');

// str :: a -> String
const str = x =>
Array.isArray(x) && x.every(
v => ('string' === typeof v) && (1 === v.length)
) ? (
x.join('')
) : x.toString();

// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = n =>
// The first n elements of a list,
// string of characters, or stream.
xs => 'GeneratorFunction' !== xs
.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], Array.from({
length: n
}, () => {
const x = xs.next();
return x.done ? [] : [x.value];
}));

// takeWhile :: (a -> Bool) -> [a] -> [a]
// takeWhile :: (Char -> Bool) -> String -> String
const takeWhile = p =>
xs => (
n => xs.slice(
0, 0 < n ? until(
i => n === i || !p(xs[i])
)(i => 1 + i)(0) : 0
)
)(xs.length);

// transpose :: [[a]] -> [[a]]
const transpose = xss => {
// If some of the rows are shorter than the following rows,
// their elements are skipped:
// > transpose [[10,11],[20],[],[30,31,32]] == [[10,20,30],[11,31],[32]]
const go = xss =>
0 < xss.length ? (() => {
const
h = xss[0],
t = xss.slice(1);
return 0 < h.length ? [
[h[0]].concat(t.reduce(
(a, xs) => a.concat(
0 < xs.length ? (
[xs[0]]
) : []
),
[]
))
].concat(go([h.slice(1)].concat(
t.map(xs => xs.slice(1))
))) : go(t);
})() : [];
return go(xss);
};

// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = p => f => x => {
let v = x;
while (!p(v)) v = f(v);
return v;
};

// unwords :: [String] -> String
const unwords = xs =>
// A space-separated string derived
// from a list of words.
xs.join(' ');

// quoted :: Char -> String -> String
const quoted = c =>
// A string flanked on both sides
// by a specified quote character.
s => c + s + c;

// words :: String -> [String]
const words = s =>
// List of space-delimited sub-strings.
s.split(/\s+/);

// zipWithList :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = f =>
// A list constructed by zipping with a
// custom function, rather than with the
// default tuple constructor.
xs => ys => ((xs_, ys_) => {
const lng = Math.min(length(xs_), length(ys_));
return take(lng)(xs_).map(
(x, i) => f(x)(ys_[i])
);
})([...xs], [...ys]);

// MAIN ---
return main();
})();
```
Output:
```Longest common suffix:

throne saxophone tone -> 'one'
prefix suffix infix -> 'fix'
remark spark aardvark lark -> 'ark'
ectoplasm banana brick -> ''```

jq

Works with: jq

Works with gojq, the Go implementation of jq

This entry uses `longest_common_prefix` from Longest_common_suffix#jq and so the definition is not repeated here.

```# Input: an array of strings
def longest_common_suffix:
def r: explode | reverse | implode;
if length == 0 then ""        # by convention
elif length == 1 then .[0]    # for speed
else map(r)
| longest_common_prefix
| r
end;```

Test Cases

```def test:
["baabababc","baabc","bbbabc"],
["baabababc","baabc","bbbazc"],
[""],
[],
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
["throne","cone", "bone"]
| "\(.) => \(longest_common_suffix)";

test```
Output:
```["baabababc","baabc","bbbabc"] => abc
["baabababc","baabc","bbbazc"] => c
[""] =>
[] =>
["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"] => day
["throne","cone","bone"] => one
```

Julia

```function longestcommonsuffix(strings)
n, nmax = 0, minimum(length, strings)
nmax == 0 && return ""
while n <= nmax && all(s -> s[end-n] == strings[end][end-n], strings)
n += 1
end
return strings[1][end-n+1:end]
end

println(longestcommonsuffix(["baabababc","baabc","bbbabc"]))
println(longestcommonsuffix(["baabababc","baabc","bbbazc"]))
println(longestcommonsuffix([""]))
```
Output:
```abc
c
```

Kotlin

Translation of: Go
```fun lcs(a: List<String>): String {
val le = a.size
if (le == 0) {
return ""
}
if (le == 1) {
return a[0]
}
val le0 = a[0].length
var minLen = le0
for (i in 1 until le) {
if (a[i].length < minLen) {
minLen = a[i].length
}
}
if (minLen == 0) {
return ""
}
var res = ""
val a1 = a.subList(1, a.size)
for (i in 1..minLen) {
val suffix = a[0].substring(le0 - i)
for (e in a1) {
if (!e.endsWith(suffix)) {
return res
}
}
res = suffix
}
return ""
}

fun main() {
val tests = listOf(
listOf("baabababc", "baabc", "bbbabc"),
listOf("baabababc", "baabc", "bbbazc"),
listOf("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"),
listOf("longest", "common", "suffix"),
listOf("suffix"),
listOf("")
)
for (test in tests) {
println("\$test -> `\${lcs(test)}`")
}
}
```
Output:
```[baabababc, baabc, bbbabc] -> `abc`
[baabababc, baabc, bbbazc] -> `c`
[Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] -> `day`
[longest, common, suffix] -> ``
[suffix] -> `suffix`
[] -> `````

Ksh

```#!/bin/ksh

# Longest common suffix

#	# Variables:
#
typeset -a arr1=( "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" )
typeset -a arr2=( "baabababc" "baabc" "bbbabc" )
typeset -a arr3=( "baabababc" "babc" "bbbabc" )
typeset -a arr4=( "longest" "common" "suffix" )
typeset -a arr5=( "suffix" )
typeset -a arr6=( "" )

#	# Functions:
#

#	# Function _minlenele(arr) - return the shortest element in an array
#
function _minlenele {
typeset _arr ; nameref _arr="\$1"
typeset _min _i ; integer _i

_min=\${_arr[0]}
for ((_i=1; _i<\${#_arr[*]}; _i++)); do
(( \${#_arr[_i]} < \${#_min} )) && _min=\${_arr[_i]}
done
echo "\${_min}"
}

######
# main #
######

for array in arr1 arr2 arr3 arr4 arr5 arr6; do
nameref arr=\${array}
printf "\n( %s ) -> " "\${arr[*]}"
suffix=\$(_minlenele arr)
for ((j=\${#suffix}; j>0; j--)); do
for ((i=0; i<\${#arr[*]}; i++)); do
[[ \${arr[i]%\${suffix: -\${j}}} == \${arr[i]} ]] && continue 2
done
printf "'%s'" \${suffix: -\${j}}
break
done
typeset +n arr
done
echo
```
Output:
```( Sunday Monday Tuesday Wednesday Thursday Friday Saturday ) -> 'day'
( baabababc baabc bbbabc ) -> 'abc'
( baabababc babc bbbabc ) -> 'babc'
( longest common suffix ) ->
( suffix ) -> 'suffix'
(  ) ->
```

Mathematica/Wolfram Language

```ClearAll[LCS]
LCS[x_List] := Module[{l, s},
If[Length[x] > 0,
l = Min[StringLength /@ x];
s = Characters[StringTake[x, -l]];
s //= Transpose;
l = LengthWhile[Reverse@s, Apply[SameQ]];
StringTake[First[x], -l]
,
""
]
]
LCS[{"throne", "sousaphone"}]
LCS[{"prefix", "suffix"}]
LCS[{"remark", "spark", "aardvark"}]
LCS[{"throne", "", "throne"}]
LCS[{"throne", "throne"}]
LCS[{"cheese"}]
LCS[{""}]
LCS[{}]
LCS[{"ectoplasm", "banana"}]
```
Output:
```"one"
"fix"
"ark"
""
"throne"
"cheese"
""
""
""```

Nim

```import sequtils, strformat, strutils

func lcs(list: varargs[string]): string =
if list.len == 0: return
result = list[0]
for i in 1..list.high:
var newLength = 0
for j in 1..result.len:
if j > list[i].len or list[i][^j] != result[^j]:
break
inc newLength
result = result[^newLength..^1]

proc test(list: varargs[string]) =
let lst = list.mapIt('"' & it & '"').join(", ")
echo &"lcs({lst}) = \"{lcs(list)}\""

test("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
test("throne", "throne")
test("throne", "dungeon")
test("cheese")
test("")
test()
test("prefix", "suffix")
test("send", "lend")
```
Output:
```lcs("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") = "day"
lcs("throne", "throne") = "throne"
lcs("throne", "dungeon") = ""
lcs("cheese") = "cheese"
lcs("") = ""
lcs() = ""
lcs("prefix", "suffix") = "fix"
lcs("send", "lend") = "end"```

Perl

Based on Longest_common_prefix Perl entry.

```use strict;
use warnings;
use feature 'say';

sub lcs {
for (0..\$#_) { \$_[\$_] = reverse \$_[\$_] }
join '', reverse split '', (join("\0", @_) =~ /^ ([^\0]*) [^\0]* (?:\0 \1 [^\0]*)* \$/sx)[0];
}

for my \$words (
[ <Sunday Monday Tuesday Wednesday Thursday Friday Saturday> ],
[ <Sondag Maandag Dinsdag Woensdag Donderdag Vrydag Saterdag dag> ],
[ 2347, 9312347, 'acx5g2347', 12.02347 ],
[ <longest common suffix> ],
[ ('one, Hey!', 'three, Hey!', 'ale, Hey!', 'me, Hey!') ],
[ 'suffix' ],
[ '' ]) {
say qq{'@\$words' ==> '@{[lcs(@\$words)]}';
}
```
Output:
```'Sunday Monday Tuesday Wednesday Thursday Friday Saturday' ==> 'day'
'Sondag Maandag Dinsdag Woensdag Donderdag Vrydag Saterdag dag' ==> 'dag'
'2347 9312347 acx5g2347 12.02347' ==> '2347'
'longest common suffix' ==> ''
'one, Hey! three, Hey! ale, Hey! me, Hey!' ==> 'e, Hey!'
'suffix' ==> 'suffix'
'' ==> ''```

Phix

Phix allows negative indexes, with -1 as the last element [same as \$], and -length(s) the first element of s, so we can just do this:

```with javascript_semantics
function longestcommonsuffix(sequence strings)
string res = ""
if length(strings) then
res = strings[1]
for i=2 to length(strings) do
string si = strings[i]
if length(si)<length(res) then
res = res[-length(si)..\$]
end if
for j=-1 to -length(res) by -1 do
if res[j]!=si[j] then
res = res[j+1..\$]
exit
end if
end for
if length(res)=0 then exit end if
end for
end if
return res
end function

sequence tests = {{"baabababc","baabc","bbbabc"},
{"baabababc","baabc","bbbazc"},
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
{"longest", "common", "suffix"},
{"suffix"},
{""}}
for i=1 to length(tests) do
printf(1,"%v ==> \"%s\"\n",{tests[i],longestcommonsuffix(tests[i])})
end for
```
Output:
```{"baabababc","baabc","bbbabc"} ==> "abc"
{"baabababc","baabc","bbbazc"} ==> "c"
{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"} ==> "day"
{"longest","common","suffix"} ==> ""
{"suffix"} ==> "suffix"
{""} ==> ""
```

Python

Pending a fuller task statement and some test samples:

Works with: Python version 3
```'''Longest common suffix'''

from itertools import takewhile
from functools import reduce

# longestCommonSuffix :: [String] -> String
def longestCommonSuffix(xs):
'''Longest suffix shared by all
strings in xs.
'''
def allSame(cs):
h = cs[0]
return all(h == c for c in cs[1:])

def firstCharPrepended(s, cs):
return cs[0] + s
return reduce(
firstCharPrepended,
takewhile(
allSame,
zip(*(reversed(x) for x in xs))
),
''
)

# -------------------------- TEST --------------------------
# main :: IO ()
def main():
'''Test'''

samples = [
[
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
], [
"Sondag", "Maandag", "Dinsdag", "Woensdag",
"Donderdag", "Vrydag", "Saterdag"
]
]
for xs in samples:
print(
longestCommonSuffix(xs)
)

# MAIN ---
if __name__ == '__main__':
main()
```
Output:
```day
dag```

Quackery

`commonprefix` is defined at Longest common prefix#Quackery.

```  [ [] swap
witheach
[ reverse nested join ]
commonprefix
reverse ]                 is commonsuffix ( [ --> \$ )

\$ "monday tuesday wednesday thursday friday saturday sunday"
nest\$ commonsuffix echo\$```
Output:
`day`

Raku

Works with: Rakudo version 2020.07
```sub longest-common-suffix ( *@words ) {
return '' unless +@words;
my \$min = @words».chars.min;
for 1 .. * {
return @words[0].substr(* - \$min) if \$_ > \$min;
next if @words».substr(* - \$_).Set == 1;
return @words[0].substr(* - \$_ + 1);
}
}

say "{\$_.raku} - LCS: >{longest-common-suffix \$_}<" for
<Sunday Monday Tuesday Wednesday Thursday Friday Saturday>,
<Sondag Maandag Dinsdag Woensdag Donderdag Vrydag Saterdag dag>,
( 2347, 9312347, 'acx5g2347', 12.02347 ),
<longest common suffix>,
('one, Hey!', 'three, Hey!', 'ale, Hey!', 'me, Hey!'),
'suffix',
''
```
Output:
```("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") - LCS: >day<
("Sondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrydag", "Saterdag", "dag") - LCS: >dag<
(2347, 9312347, "acx5g2347", 12.02347) - LCS: >2347<
("longest", "common", "suffix") - LCS: ><
("one, Hey!", "three, Hey!", "ale, Hey!", "me, Hey!") - LCS: >e, Hey!<
"suffix" - LCS: >suffix<
"" - LCS: ><```

REXX

Essentially,   this REXX version simply reversed the strings,   and then finds the longest common  prefix.

```/*REXX program finds the  longest common suffix  contained in an array of strings.      */
parse arg z;          z= space(z)                /*obtain optional arguments from the CL*/
if z==''|z==","  then z='baabababc baabc bbbabc' /*Not specified?  Then use the default.*/
z= space(z);      #= words(z)                    /*#:  the number of words in the list. */
say 'There are '  #  " words in the list: "  z
zr= reverse(z)                                   /*reverse Z, find longest common prefix*/
@= word(zr, 1);       m= length(@)               /*get 1st word in reversed string; len.*/

do j=2  to #;    x= word(zr, j)             /*obtain a word (string) from the list.*/
t= compare(@, x)                            /*compare to the "base" word/string.   */
if t==1          then do;  @=;  leave       /*A mismatch of strings?   Then leave, */
end                   /*no sense in comparing anymore strings*/
if t==0 & @==x   then t= length(@) + 1      /*Both strings equal?  Compute length. */
if t>=m  then iterate                       /*T ≥ M?  Then it's not longest string.*/
m= t - 1;        @= left(@, max(0, m) )     /*redefine max length & the base string*/
end   /*j*/
say                                              /*stick a fork in it,  we're all done. */
if m==0  then say 'There is no common suffix.'
else say 'The longest common suffix is: '   right( word(z, 1), m)
```
output   when using the default input:
```There are  3  words in the list:  baabababc baabc bbbabc

The longest common suffix is:  abc
```

Ring

```load "stdlib.ring"

pre = ["baabababc","baabc","bbbabc"]
len = len(pre)
lenList = list(len)
sub = list(len)

see "Input:" + nl
see pre

for n = 1 to len
temp = pre[n]
pre[n] = rever(temp)
next

for n = 1 to len
lenList[n] = len(pre[n])
next

lenList = sort(lenList)
lenMax = lenList[1]

for m = 1 to lenMax
check = 0
sub1 = substr(pre[1],1,m)
sub2 = substr(pre[2],1,m)
sub3 = substr(pre[3],1,m)
if sub1 = sub2 and sub2 = sub3
check = 1
ok
if check = 1
longest = m
ok
next

longPrefix = substr(pre[1],1,longest)
longPrefix = rever(longPrefix)

see "Longest common suffix = " + longPrefix + nl

func rever(cstr)
cStr2 = ""
for x = len(cStr) to 1 step -1
cStr2 = cStr2 + cStr[x]
next
return cStr2```
Output:
```Input:
baabababc
baabc
bbbabc
Longest common suffix = abc
```

Ruby

Testcases taken from Go.

```tests = [["baabababc", "baabc", "bbbabc"],
["baabababc", "baabc", "bbbazc"],
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
["longest", "common", "suffix"],
["suffix"],
[""],
]
def lcs(ar)
i = (0..ar.first.size).detect{|s| ar.all?{|word| word.end_with? ar.first[s..-1]} }
ar.first[i..-1]
end

tests.each{|test| p lcs(test) }
```
Output:
```"abc"
"c"
"day"
""
"suffix"
""
```

sed

```\$q
N
s/\(.*\)\(\n\).*\1\$/\2\1/
D
```
```\$ printf '%s\n' Sunday '' Monday Tuesday | sed -f suffix.sed

\$ printf '%s\n' Sunday Monday Tuesday | sed -f suffix.sed
day
\$ printf '%s\n' Sunday Monday | sed -f suffix.sed
nday
```

Standard ML

```val lcs =
let
val commonSuffix = fn (s0, s1) =>
let
val rec pairTakeREq = fn (0, _) => s0 | (_, 0) => s1 | (i, j) =>
let
val i' = i - 1 and j' = j - 1
in
if String.sub (s0, i') = String.sub (s1, j')
then pairTakeREq (i', j')
else String.extract (s0, i, NONE)
end
in
pairTakeREq (size s0, size s1)
end
in
fn [] => "" | x :: xs => foldl commonSuffix x xs
end
```

V (Vlang)

Translation of: go
```fn lcs(a []string) string {
// Special cases first
match a.len {
0 {
return ""
}
1 {
return a[0]
}
else {}
}
le0 := a[0].len
mut min_len := le0
for i in 1..a.len {
if a[i].len < min_len {
min_len = a[i].len
}
}
if min_len == 0 {
return ""
}
mut res := ""
a1 := a[1..]
for i := 1; i <= min_len; i++ {
suffix := a[0][le0-i..]
for e in a1 {
if e.index(suffix) or {0} + suffix.len != e.len {
return res
}
}
res = suffix
}
return res
}

// Normally something like this would be a Testlcs function in *_test.go
// and use the testing package to report failures.
fn main() {
for l in [
["baabababc", "baabc", "bbbabc"],
["baabababc", "baabc", "bbbazc"],
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
["longest", "common", "suffix"],
["suffix"],
[""],
] {
println("lcs(\$l) = \${lcs(l)}")
}
}```
Output:
`Same as Go entry`

Wren

```var lcs = Fn.new { |a|
if (a.count == 0) return ""
if (a.count == 1) return a[0]
var minLen = a.reduce(a[0].count) { |min, s| (s.count < min) ? s.count : min }
if (minLen == 0) return ""
var res = ""
for (i in 1..minLen) {
var suffix = a[0][-i..-1]
for (e in a.skip(1)) {
if (!e.endsWith(suffix)) return res
}
res = suffix
}
return res
}

var tests = [
["baabababc","baabc","bbbabc"],
["baabababc","baabc","bbbazc"],
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
["longest", "common", "suffix"],
["suffix"],
[""]
]
for (test in tests) System.print("%(test) -> \"%(lcs.call(test))\"")
```
Output:
```[baabababc, baabc, bbbabc] -> "abc"
[baabababc, baabc, bbbazc] -> "c"
[Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] -> "day"
[longest, common, suffix] -> ""
[suffix] -> "suffix"
[] -> ""
```

XPL0

```include xpllib;         \for StrRev

proc LCS(N, Strs);      \Show longest common suffix
int  N;  char Strs;
int  I, J, C;
[for I:= 0 to N-1 do    \work with reversed strings
StrRev(@Strs(I,0));
J:= 0;
loop   [C:= Strs(0,J);
if C = 0 then quit;
for I:= 1 to N-1 do
if Strs(I,J) # C then quit;
J:= J+1;
];
ChOut(0, ^");
for I:= J-1 downto 0 do
ChOut(0, Strs(0,I));
ChOut(0, ^");
CrLf(0);
for I:= 0 to N-1 do     \undo reversal (for extra credit?)
StrRev(@Strs(I,0));
];

int Tests, I;
[Tests:= [
[3, "baabababc","baabc","bbbabc"],
[3, "baabababc","baabc","bbbazc"],
[7, "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
[3, "longest", "common", "suffix"],
[1, "suffix"],
[1, ""] ];
for I:= 0 to 6-1 do
LCS(Tests(I,0), @Tests(I,1));
]```
Output:
```"abc"
"c"
"day"
""
"suffix"
""
```