Longest palindromic substrings: Difference between revisions

Added Easylang
(Added 11l)
(Added Easylang)
 
(17 intermediate revisions by 13 users not shown)
Line 11:
 
=={{header|11l}}==
<langsyntaxhighlight lang="11l">F longest_palindrome(s)
V t = Array(‘^’s‘$’).join(‘#’)
V n = t.len
Line 35:
‘drome’,
‘the abbatial palace’]
print(‘'’s‘' -> '’longest_palindrome(s)‘'’)</langsyntaxhighlight>
 
{{out}}
Line 45:
'drome' -> 'e'
'the abbatial palace' -> 'abba'
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">BYTE FUNC Palindrome(CHAR ARRAY s)
BYTE l,r
 
l=1 r=s(0)
WHILE l<r
DO
IF s(l)#s(r) THEN RETURN (0) FI
l==+1 r==-1
OD
RETURN (1)
 
PROC Find(CHAR ARRAY text,res)
BYTE first,len
len=text(0)
WHILE len>0
DO
FOR first=1 TO text(0)-len+1
DO
SCopyS(res,text,first,first+len-1)
IF Palindrome(res) THEN
RETURN
FI
OD
len==-1
OD
res(0)=0
RETURN
 
PROC Test(CHAR ARRAY text)
CHAR ARRAY res(100)
 
Find(text,res)
PrintF("""%S"" -> ""%S""%E",text,res)
RETURN
 
PROC Main()
Test("three old rotators")
Test("never reverse")
Test("abracadabra")
Test("the abbatial palace")
Test("qwertyuiop")
Test("")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Longest_palindromic_substrings.png Screenshot from Atari 8-bit computer]
<pre>
"three old rotators" -> "rotator"
"never reverse" -> "ever reve"
"abracadabra" -> "aca"
"the abbatial palace" -> "abba"
"qwertyuiop" -> "q"
"" -> ""
</pre>
 
=={{header|ALGOL 68}}==
Palindromes of length 1 or more are detected, finds the left most palindrome if there are several of the same length.<br>
Treats upper and lower case as distinct and does not require the characters to be letters.
<syntaxhighlight lang="algol68">BEGIN # find the longest palindromic substring of a string #
# returns the length of s #
OP LENGTH = ( STRING s )INT: ( UPB s + 1 ) - LWB s;
# returns s right-padded with blanks to at least w characters or s if it is already wide enough #
PRIO PAD = 1;
OP PAD = ( STRING s, INT w )STRING:
BEGIN
STRING result := s;
WHILE LENGTH result < w DO result +:= " " OD;
result
END # PAD # ;
# returns the longest palindromic substring of s #
# if there are multiple substrings with the longest length, the leftmost is returned #
PROC longest palindromic substring = ( STRING s )STRING:
IF LENGTH s < 2
THEN s
ELSE
INT lwb s = LWB s;
INT upb s = UPB s;
STRING result := s[ lwb s ];
IF s[ lwb s + 1 ] = s[ lwb s ] THEN
# the first two characters are a palindrome #
result +:= s[ lwb s + 1 ]
FI;
FOR i FROM lwb s + 1 TO upb s - 1 DO
INT p start := i;
INT p end := i + 1;
IF IF s[ i - 1 ] = s[ i + 1 ] THEN
# odd length palindrome at i - 1 #
p start -:= 1;
TRUE
ELIF s[ i ] = s[ i + 1 ] THEN
# even length palindrome at i #
TRUE
ELSE FALSE
FI
THEN
# have a palindrome at p start : p end #
# attempt to enlarge the range #
WHILE IF p start = lwb s OR p end = upb s
THEN FALSE
ELSE s[ p start - 1 ] = s[ p end + 1 ]
FI
DO # can extend he palindrome #
p start -:= 1;
p end +:= 1
OD;
IF ( p end + 1 ) - p start > LENGTH result
THEN
# have a longer palindrome #
result := s[ p start : p end ]
FI
FI
OD;
result
FI # longest palindromic substring # ;
# finds the longest palindromic substring of s and checks it is the expacted value #
PROC test = ( STRING s, expected value )VOID:
BEGIN
STRING palindrome = longest palindromic substring( s );
print( ( ( """" + s + """" ) PAD 38, " -> ", ( """" + palindrome + """" ) PAD 36
, IF palindrome = expected value THEN "" ELSE " NOT " + expected value + " ???" FI
, newline
)
)
END # test longest palindromic substring # ;
test( "three old rotators", "rotator" );
test( "never reverse", "ever reve" );
test( "stable was I ere I saw elbatrosses", "table was I ere I saw elbat" );
test( "abracadabra", "aca" );
test( "drome", "d" );
test( "x", "x" );
test( "the abbatial palace", "abba" );
test( "", "" );
test( "abcc", "cc" );
test( "abbccc", "ccc" )
END</syntaxhighlight>
{{out}}
<pre>
"three old rotators" -> "rotator"
"never reverse" -> "ever reve"
"stable was I ere I saw elbatrosses" -> "table was I ere I saw elbat"
"abracadabra" -> "aca"
"drome" -> "d"
"x" -> "x"
"the abbatial palace" -> "abba"
"" -> ""
"abcc" -> "cc"
"abbccc" -> "ccc"
</pre>
 
=={{header|Arturo}}==
{{trans|Nim}}
<syntaxhighlight lang="rebol">palindrome?: function [str]-> str = join reverse split str
 
lps: function [s][
maxLength: 0
result: new []
loop 0..dec size s 'fst [
loop fst..dec size s 'lst [
candidate: slice s fst lst
if palindrome? candidate [
if? maxLength < size candidate [
result: new @[candidate]
maxLength: size candidate
]
else [
if maxLength = size candidate ->
'result ++ candidate
]
]
]
]
 
return (maxLength > 1)? -> result
-> []
]
 
loop ["babaccd", "rotator", "several", "palindrome", "piété", "tantôt", "étêté"] 'str [
palindromes: lps str
print [str "->" (0 < size palindromes)? -> join.with:", " palindromes
-> "X"]
]</syntaxhighlight>
 
{{out}}
 
<pre>babaccd -> bab, aba
rotator -> rotator
several -> eve
palindrome -> X
piété -> été
tantôt -> tôt
étêté -> étêté</pre>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">LPS(str){
found := [], result := [], maxL := 0
while (StrLen(str) >= 2 && StrLen(str) >= maxL){
s := str
loop {
while (SubStr(s, 1, 1) <> SubStr(s, 0)) ; while 1st chr <> last chr
s := SubStr(s, 1, StrLen(s)-1) ; trim last chr
if (StrLen(s) < 2 || StrLen(s) < maxL )
break
if (s = reverse(s)){
found.Push(s)
maxL := maxL < StrLen(s) ? StrLen(s) : maxL
break
}
s := SubStr(s, 1, StrLen(s)-1) ; trim last chr
}
str := SubStr(str, 2) ; trim 1st chr and try again
}
maxL := 0
for i, str in found
maxL := maxL < StrLen(str) ? StrLen(str) : maxL
for i, str in found
if (StrLen(str) = maxL)
result.Push(str)
return result
}
reverse(s){
for i, v in StrSplit(s)
output := v output
return output
}</syntaxhighlight>
Examples:<syntaxhighlight lang="autohotkey">db =
(
three old rotators
never reverse
stable was I ere I saw elbatrosses
abracadabra
drome
x
the abbatial palace
)
 
for i, line in StrSplit(db, "`n", "`r"){
result := "[""", i := 0
for i, str in LPS(line)
result .= str """, """
output .= line "`t> " Trim(result, """, """) (i?"""":"") "]`n"
}
MsgBox % output
return</syntaxhighlight>
{{out}}
<pre>three old rotators > ["rotator"]
never reverse > ["ever reve"]
stable was I ere I saw elbatrosses > ["table was I ere I saw elbat"]
abracadabra > ["aca", "ada"]
drome > []
x > []
the abbatial palace > ["abba"]
</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight>
func$ reverse s$ .
a$[] = strchars s$
for i = 1 to len a$[] div 2
swap a$[i] a$[len a$[] - i + 1]
.
return strjoin a$[]
.
func palin s$ .
if s$ = reverse s$
return 1
.
return 0
.
func$ lpali st$ .
for n = 1 to len st$ - 1
for m = n + 1 to len st$
sub$ = substr st$ n (m - n)
if palin sub$ = 1
if len sub$ > len max$
max$ = sub$
.
.
.
.
return max$
.
for s$ in [ "three old rotators" "never reverse" "stable was I ere I saw elbatrosses" "abracadabra" "drome" "the abbatial palace" ]
print lpali s$
.
</syntaxhighlight>
{{out}}
<pre>
rotator
ever reve
table was I ere I saw elbat
aca
d
abba
</pre>
 
=={{header|F_Sharp|F#}}==
===Manacher Function===
<langsyntaxhighlight lang="fsharp">
// Manacher Function. Nigel Galloway: October 1st., 2020
let Manacher(s:string) = let oddP,evenP=Array.zeroCreate s.Length,Array.zeroCreate s.Length
Line 64 ⟶ 360:
match (Ʃ+evenP.[Ʃ])>g with true->fGe (Ʃ-evenP.[Ʃ]+1) (Ʃ+evenP.[Ʃ]) (Ʃ+1) |_->fGe n g (Ʃ+1)
(fGo 0 -1 0,fGe 0 -1 0)
</syntaxhighlight>
</lang>
 
===The Task===
<langsyntaxhighlight lang="fsharp">
let fN g=if g=[||] then (0,0) else g|>Array.mapi(fun n g->(n,g))|>Array.maxBy snd
let lpss s=let n,g=Manacher s in let n,g=fN n,fN g in if (snd n)*2+1>(snd g)*2 then s.[(fst n)-(snd n)..(fst n)+(snd n)] else s.[(fst g)-(snd g)+1..(fst g)+(snd g)]
let test = ["three old rotators"; "never reverse"; "stable was I ere I saw elbatrosses"; "abracadabra"; "drome"; "the abbatial palace"; ""]
test|>List.iter(fun n->printfn "A longest palindromic substring of \"%s\" is \"%s\"" n (lpss n))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 83 ⟶ 379:
A longest palindromic substring of "" is ""
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vbnet">Function isPalindrome(s As String) As Integer
For i As Integer = 1 To Len(s) / 2
If Mid(s, i, 1) <> Mid(s, Len(s) - i + 1, 1) Then Return False
Next i
Return True
End Function
 
Sub LongestPalindrome(s As String)
Dim As String substr, longest = ""
Dim As Integer i, j
For i = 1 To Len(s)
For j = i To Len(s)
substr = Mid(s, i, j - i + 1)
If isPalindrome(substr) Andalso Len(substr) > Len(longest) Then longest = substr
Next j
Next i
Print "The longest palindromic substring is/are: "
For i = 1 To Len(s)
For j = i To Len(s)
substr = Mid(s, i, j - i + 1)
If IsPalindrome(substr) Andalso Len(substr) = Len(longest) Andalso Len(substr) > 2 Then Print substr; " ";
Next j
Next i
If Len(longest) <= 2 Then Print "<no palindromic substring of two of more letters found>"
End Sub
 
Dim s As String
Input "Enter a string: ", s
 
LongestPalindrome(s)
 
Sleep</syntaxhighlight>
 
=={{header|Go}}==
{{trans|Wren}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 152 ⟶ 483:
fmt.Printf(" %-13s Length %d -> %v\n", s, len(longest[0]), longest)
}
}</langsyntaxhighlight>
 
{{out}}
Line 169 ⟶ 500:
A list version, written out of curiosity. A faster approach could be made with an indexed datatype.
 
<langsyntaxhighlight lang="haskell">-------------- LONGEST PALINDROMIC SUBSTRINGS ------------
 
longestPalindromes :: String -> ([String], Int)
Line 226 ⟶ 557:
where
rjust n c = drop . length <*> (replicate n c ++)
w = maximum (length . xShow <$> xs)</langsyntaxhighlight>
{{Out}}
<pre>Longest palindromic substrings:
Line 237 ⟶ 568:
"the abbatial palace" -> (["abba"],4)
"" -> ([],0)</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren]]'''
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">def longestPalindromicSubstring:
length as $len
| if $len <= 1 then .
else explode as $s
| {targetLen: $len, longest: [], i: 0}
| until(.stop;
(.i + .targetLen - 1) as $j
| if $j < $len
then $s[.i:$j+1] as $ss
| if $ss == ($ss|reverse) then .longest += [$ss] else . end
| .i += 1
else
if .longest|length > 0 then .stop=true else . end
| .i = 0
| .targetLen += - 1
end )
| .longest
| map(implode)
| unique
end ;
def strings:
["babaccd", "rotator", "reverse", "forever", "several", "palindrome", "abaracadaraba"];
 
"The palindromic substrings having the longest length are:",
(strings[]
| longestPalindromicSubstring as $longest
| " \(.): length \($longest[0]|length) -> \($longest)"
)</syntaxhighlight>
 
{{out}}
<pre>
The palindromic substrings having the longest length are:
babaccd: length 3 -> ["aba","bab"]
rotator: length 7 -> ["rotator"]
reverse: length 5 -> ["rever"]
forever: length 5 -> ["rever"]
several: length 3 -> ["eve"]
palindrome: length 1 -> ["a","d","e","i","l","m","n","o","p","r"]
abaracadaraba: length 3 -> ["aba","aca","ada","ara"]
</pre>
 
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">function allpalindromics(s)
list, len = String[], length(s)
for i in 1:len-1, j in i+1:len
Line 256 ⟶ 634:
join(list[findall(x -> length(x) == length(list[end]), list)], "\" or \""), "\"")
end
</langsyntaxhighlight>{{out}}
<pre>
The longest palindromic substring of babaccd is: "bab" or "aba"
Line 267 ⟶ 645:
 
===Manacher algorithm===
<langsyntaxhighlight lang="julia">
function manacher(str)
s = "^" * join(split(str, ""), "#") * "\$"
Line 292 ⟶ 670:
"The longest palindromic substring of $teststring is: \"$pal\"")
end
</langsyntaxhighlight>{{out}}
<pre>
The longest palindromic substring of babaccd is: "aba"
Line 301 ⟶ 679:
No palindromes of 2 or more letters found in "palindrome."
The longest palindromic substring of abaracadabra is: "ara"
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[ExpandSubsequenceTry, LongestPalindromicSubsequence]
ExpandSubsequenceTry[seq_List, beginpos : {a_, b_}] :=
Module[{len, maxbroaden, last},
len = Length[seq];
maxbroaden = Min[a - 1, len - b];
last = maxbroaden;
Do[
If[! PalindromeQ[Take[seq, {a - j, b + j}]],
last = j - 1;
Break[];
]
,
{j, maxbroaden}
];
{a - last, b + last}
]
LongestPalindromicSubsequence[l_List] :=
Module[{evenposs, oddposs, subseqs},
evenposs = SequencePosition[l, {x_, x_}];
oddposs = SequencePosition[l, {x_, y_, x_}];
subseqs = Join[evenposs, oddposs];
subseqs = ExpandSubsequenceTry[l, #] & /@ subseqs;
If[Length[subseqs] > 0,
TakeLargestBy[Take[l, #] & /@ subseqs, Length, 1][[1]]
,
{}
]
]
StringJoin@LongestPalindromicSubsequence[Characters["three old rotators"]]
StringJoin@LongestPalindromicSubsequence[Characters["never reverse"]]
StringJoin@LongestPalindromicSubsequence[Characters["stable was I ere I saw elbatrosses"]]
StringJoin@LongestPalindromicSubsequence[Characters["abracadabra"]]
StringJoin@LongestPalindromicSubsequence[Characters["drome"]]
StringJoin@LongestPalindromicSubsequence[Characters["the abbatial palace"]]</syntaxhighlight>
{{out}}
<pre>"rotator"
"ever reve"
"table was I ere I saw elbat"
"aca"
""
"abba"</pre>
 
=={{header|Nim}}==
Simple algorithm but working on Unicode code points.
<syntaxhighlight lang="nim">import sequtils, strutils, unicode
 
func isPalindrome(s: seq[Rune]): bool =
## Return true if a sequence of runes is a palindrome.
for i in 1..(s.len shr 1):
if s[i - 1] != s[^i]:
return false
result = true
 
func lps(s: string): seq[string] =
var maxLength = 0
var list: seq[seq[Rune]]
let r = s.toRunes
for first in 0..r.high:
for last in first..r.high:
let candidate = r[first..last]
if candidate.isPalindrome():
if candidate.len > maxLength:
list = @[candidate]
maxLength = candidate.len
elif candidate.len == maxLength:
list.add candidate
if maxLength > 1:
result = list.mapIt($it)
 
for str in ["babaccd", "rotator", "several", "palindrome", "piété", "tantôt", "étêté"]:
let result = lps(str)
if result.len == 0:
echo str, " → ", "<no palindromic substring of two of more letters found>"
else:
echo str, " → ", result.join(", ")</syntaxhighlight>
 
{{out}}
<pre>babaccd → bab, aba
rotator → rotator
several → eve
palindrome → <no palindromic substring of two of more letters found>
piété → été
tantôt → tôt
étêté → étêté</pre>
 
=={{header|Pascal}}==
==={{header|Free Pascal}}===
<syntaxhighlight lang="pascal">
program FindLongestPalindrome;
 
uses
SysUtils,strutils;
 
const
arr: array of string = ('three old rotators', 'never reverse', 'stable was I ere I saw elbatrosses', 'abracadabra', 'drome', 'the abbatial palace', '');
 
var
st, longestPalindrome, dummy: string;
i, j, longest: integer;
 
begin
for st in arr do
begin
longest := 0;
longestPalindrome := '';
for i := 1 to Length(st) do
begin
for j := Length(st) downto i do
begin
dummy := Copy(st, i, j - i + 1);
if (j - i + 1 > longest) and (dummy = ReverseString(dummy)) then
begin
longest := j - i + 1;
longestPalindrome := dummy;
end;
end;
end;
WriteLn(Format('%-35s -> %s', [st, longestPalindrome]));
end;
end.
 
</syntaxhighlight>
{{out}}
<pre>
three old rotators -> rotator
never reverse -> ever reve
stable was I ere I saw elbatrosses -> table was I ere I saw elbat
abracadabra -> aca
drome -> d
the abbatial palace -> abba
->
</pre>
 
=={{header|Perl}}==
The short one - find all palindromes with one regex.
<syntaxhighlight lang="perl">use strict;
<lang perl>#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Longest_palindromic_substrings
use warnings;
 
Line 318 ⟶ 828:
pop =~ /(.+) .? (??{reverse $1}) (?{ $best[length $&]{$&}++ }) (*FAIL)/x;
keys %{pop @best};
}</langsyntaxhighlight>
{{out}}
<pre>
Line 329 ⟶ 839:
Longest Palindrome For abaracadabra = aba ara aca ada
</pre>
The faster one - does the million digits of Pi in under half a second.
<lang perl>#!/usr/bin/perl
 
The faster one - does the million digits of Pi in under half a second.
use strict; # https://rosettacode.org/wiki/Longest_palindromic_substrings
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature 'bitwise';
 
#@ARGV = 'pi.dat'; # uncomment to use this file or add filename to command line
Line 351 ⟶ 861:
my $right = substr $forward, $i, $range;
my $left = substr $backward, $length - $i, $range;
( $right ^. $left ) =~ /^\0\0+/ and # evens
($len = 2 * length $&) >= $#best and
$best[ $len ]{substr $forward, $i - length $&, $len}++;
( $right ^. "\0" . $left ) =~ /^.(\0+)/ and # odds
($len = 1 + 2 * length $1) >= $#best and
$best[ $len ]{substr $forward, $i - length $1, $len}++;
Line 369 ⟶ 879:
I, man, am regal - a German am I
toot
Warsaw was raw</langsyntaxhighlight>
{{out}}
<pre>
Line 376 ⟶ 886:
 
=={{header|Phix}}==
{{trans|Raku}}
<lang Phix>function longest_palindromes(string s)
<!--<syntaxhighlight lang="phix">(phixonline)-->
-- s = lower/strip_spaces_and_punctuation/utf8_to_utf32, if rqd
<span style="color: #000080;font-style:italic;">-- demo/rosetta/Longest_palindromic_substrings.exw (plus two older versions)</span>
integer longest = 2 -- (do not treat length 1 as palindromic)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
-- integer longest = 1 -- (do not treat length 0 as palindromic) [works just fine too]
<span style="color: #008080;">function</span> <span style="color: #000000;">longest_palindromes</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
sequence res = {}
<span style="color: #000080;font-style:italic;">-- s = lower/strip_spaces_and_punctuation/utf8_to_utf32, if rqd</span>
for i=1 to length(s) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">longest</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- (do not treat length 1 as palindromic)
for e=length(s) to i+longest-1 by -1 do
-- integer longest = 1 -- (do not treat length 0 as palindromic) [works just fine too]</span>
if s[e]=s[i] then
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
string p = s[i..e]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
integer lp = length(p)
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]?</span><span style="color: #000000;">2</span><span style="color: #0000FF;">:</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if lp>=longest and p=reverse(p) then
<span style="color: #004080;">integer</span> <span style="color: #000000;">rev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">,</span>
if lp>longest then
<span style="color: #000000;">fwd</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
longest = lp
<span style="color: #008080;">while</span> <span style="color: #000000;">rev</span><span style="color: #0000FF;"><</span><span style="color: #000000;">i</span> <span style="color: #008080;">and</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">fwd</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">rev</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">fwd</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
res = {p}
<span style="color: #000000;">rev</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
elsif not find(p,res) then -- (or just "else")
<span style="color: #000000;">fwd</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
res = append(res,p)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end if
<span style="color: #004080;">string</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">rev</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">fwd</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">lp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">lp</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">longest</span> <span style="color: #008080;">then</span>
end for
<span style="color: #008080;">if</span> <span style="color: #000000;">lp</span><span style="color: #0000FF;">></span><span style="color: #000000;">longest</span> <span style="color: #008080;">then</span>
end for
<span style="color: #000000;">longest</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lp</span>
return res -- (or "sort(res)" or "unique(res)", as needed)
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">}</span>
end function
<span style="color: #008080;">elsif</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (or just "else")</span>
 
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
constant tests = {"babaccd","rotator","reverse","forever","several","palindrome","abaracadaraba"}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for i=1 to length(tests) do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"%s: %v\n",{tests[i],longest_palindromes(tests[i])})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span> <span style="color: #000080;font-style:italic;">-- (or "sort(res)" or "unique(res)", as needed)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"babaccd"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rotator"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"reverse"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"forever"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"several"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"palindrome"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"abaracadaraba"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"abbbc"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s: %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">longest_palindromes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 413 ⟶ 932:
palindrome: {}
abaracadaraba: {"aba","ara","aca","ada"}
abbbc: {"bbb"}
</pre>
with longest initialised to 1, you get the same except for <code>palindrome: {"p","a","l","i","n","d","r","o","m","e"}</code>
 
=== faster ===
<lang Phix>function Manacher(string text)
-- Manacher's algorithm (linear time)
-- based on https://www.geeksforgeeks.org/manachers-algorithm-linear-time-longest-palindromic-substring-part-4
-- but with a few tweaks, renames, and bugfixes (in particular the < (positions-1), which I later found LIJIE already said)
sequence res = {}
integer positions = length(text)*2+1
if positions>1 then
sequence LPS = repeat(0,positions)
LPS[2] = 1
integer centerPosition = 1,
centerRightPosition = 2,
maxLPSLength = 0
for currentRightPosition=2 to positions-1 do
integer lcp = LPS[currentRightPosition+1],
diff = centerRightPosition - currentRightPosition
-- If currentRightPosition is within centerRightPosition
if diff >= 0 then
-- get currentLeftPosition iMirror for currentRightPosition
integer iMirror = 2*centerPosition-currentRightPosition + 1
lcp = min(LPS[iMirror], diff)
end if
-- Attempt to expand palindrome centered at currentRightPosition
-- Here for odd positions, we compare characters and
-- if match then increment LPS Length by ONE
-- If even position, we just increment LPS by ONE without
-- any character comparison
while ((currentRightPosition + lcp) < (positions-1) and (currentRightPosition - lcp) > 0) and
((remainder(currentRightPosition+lcp+1, 2) == 0) or
(text[floor((currentRightPosition+lcp+1)/2)+1] == text[floor((currentRightPosition-lcp-1)/2)+1] )) do
lcp += 1
end while
LPS[currentRightPosition+1] = lcp
maxLPSLength = max(lcp,maxLPSLength)
// If palindrome centered at currentRightPosition
// expand beyond centerRightPosition,
// adjust centerPosition based on expanded palindrome.
if (currentRightPosition + lcp) > centerRightPosition then
centerPosition = currentRightPosition
centerRightPosition = currentRightPosition + lcp
end if
end for
for p=1 to positions do
if LPS[p] = maxLPSLength then
integer start = floor((p-1 - maxLPSLength)/2) + 1,
finish = start + maxLPSLength - 1
string r = text[start..finish]
if not find(r,res) then
res = append(res,r)
end if
end if
end for
end if
return res
end function
include mpfr.e
mpfr pi = mpfr_init(0,-10001) -- (set precision to 10,000 dp, plus the "3.")
mpfr_const_pi(pi)
string piStr = mpfr_sprintf("%.10000Rf", pi),
s = shorten(piStr)
printf(1,"%s: %v\n",{s,Manacher(piStr)})</lang>
{{out}}
(Same as above if given the same inputs.)<br>
However, while Manacher finishes 10,000 digits in 0s, longest_palindromes takes 1s for 2,000 digits, 15s for 5,000 digits, and 2 mins for 10,000 digits,<br>
which goes to prove that longest_palindromes() above is O(n<sup><small>2</small></sup>), whereas Manacher() is O(n).<br>
<pre>
3.141592653589793238...05600101655256375679 (10,002 digits): {"398989893","020141020"}
</pre>
Then again, this is also pretty fast (same output):
{{trans|Raku}}
<lang Phix>function longest_palindromes_raku(string s)
-- s = lower/strip_spaces_and_punctuation/utf8_to_utf32, if rqd
integer longest = 2 -- (do not treat length 1 as palindromic)
-- integer longest = 1 -- (do not treat length 0 as palindromic) [works just fine too]
sequence res = {}
for i=1 to length(s) do
for j=0 to iff(i>1 and s[i-1]=s[i]?2:1) do
integer rev = j,
fwd = 1
while rev<i and i+fwd<=length(s) and s[i-rev]=s[i+fwd] do
rev += 1
fwd += 1
end while
string p = s[i-rev+1..i+fwd-1]
integer lp = length(p)
if lp>=longest then
if lp>longest then
longest = lp
res = {p}
elsif not find(p,res) then -- (or just "else")
res = append(res,p)
end if
end if
end for
end for
return res -- (or "sort(res)" or "unique(res)", as needed)
end function
 
printf(1,"%s: %v\n",{s,longest_palindromes_raku(piStr)})
s = "abbbc"
printf(1,"%s: %v\n",{s,longest_palindromes_raku(s)})</lang>
{{out}}
(first line matches the above, the second was a initially a bug)
<pre>
3.141592653589793238...05600101655256375679 (10,002 digits): {"398989893","020141020"}
abbbc: {"bbb"}
</pre>
 
=={{header|Python}}==
Line 534 ⟶ 942:
(This version ignores case but allows non-alphanumerics).
<langsyntaxhighlight lang="python">'''Longest palindromic substrings'''
 
 
Line 667 ⟶ 1,075:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Longest palindromic substrings:
Line 683 ⟶ 1,091:
This version regularizes (ignores) case and ignores non alphanumeric characters. It is only concerned with finding the ''longest'' palindromic substrings so does not exhaustively find ''all possible'' palindromes. If a palindromic substring is found to be part of a longer palindrome, it is not captured separately. Showing the longest 5 palindromic substring groups. Run it with no parameters to operate on the default; pass in a file name to run it against that instead.
 
<syntaxhighlight lang="raku" perl6line>my @chars = ( @*ARGS[0] ?? @*ARGS[0].IO.slurp !! q:to/BOB/ ) .lc.comb: /\w/;
Lyrics to "Bob" copyright Weird Al Yankovic
https://www.youtube.com/watch?v=JUQDzj6R3p4
Line 748 ⟶ 1,156:
}
 
"{.key} ({+.value})\t{.value.unique.sort}".put for @cpfoa.classify( *.chars ).sort( -*.key ).head(5);</langsyntaxhighlight>
{{out}}
Returns the length, (the count) and the list:
Line 768 ⟶ 1,176:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program finds and displays the longest palindromic string(s) in a given string. */
parse arg s /*obtain optional argument from the CL.*/
if s==''|s=="," then s='babaccd rotator reverse forever several palindrome abaracadaraba'
Line 793 ⟶ 1,201:
@= @ $ /*add a palindromic substring to a list*/
if short then return 1 /*we have found one palindrome. */
end /*j*/; return 0 /* " " " some palindrome(s). */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 847 ⟶ 1,255:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
 
Line 876 ⟶ 1,284:
see "Longest palindromic substrings:" + nl
see resList
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 891 ⟶ 1,299:
 
The Phix entry examples have been used.
<langsyntaxhighlight ecmascriptlang="wren">import "./seq" for Lst
import "./fmt" for Fmt
 
var longestPalSubstring = Fn.new { |s|
Line 919 ⟶ 1,327:
var longest = Lst.distinct(longestPalSubstring.call(s))
Fmt.print(" $-13s Length $d -> $n", s, longest[0].count, longest)
}</langsyntaxhighlight>
 
{{out}}
1,981

edits