|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
ProblemDla danych, niepustych łańcuchów tekstowych s1 i s2 należy wyznaczyć najdłuższy wspólny podłańcuch s. W porównaniu z poprzednimi zadaniami ten problem jest dosyć trudny, ponieważ nie wiemy, czego szukamy. Nie możemy zatem w normalny sposób sprawdzić, czy to coś występuje jednocześnie w łańcuchach s1 i s2. Problem wyszukiwania wspólnych sekwencji symboli jest szeroko wykorzystywany w badaniach genetycznych łańcuchów DNA, które możemy potraktować jako teksty. |
Pierwsze rozwiązanie problemu wyszukiwania najdłuższego wspólnego podłańcucha (ang. the longest common substring – LCS) jest rozwiązaniem nieoptymalnym. Nasz algorytm będzie się starał dopasowywać jak największe fragmenty łańcucha s1 do fragmentów łańcucha s2 zapamiętując najdłuższy, wyznaczony w ten sposób podłańcuch. Zasada jego pracy będzie następująca:
Wybieramy kolejne znaki łańcucha s1. Wyszukujemy w s2 wszystkie wystąpienia wybranego znaku. Po znalezieniu zgodności staramy się maksymalnie rozszerzyć pasujący fragment w prawo. Długości wyznaczonych w ten sposób wspólnych podciągów tworzą ciąg liczbowy, w którym wyszukujemy wartość maksymalną. Zapamiętujemy położenie podciągu oraz jego długość. Po przetworzeniu wszystkich znaków łańcucha s1 mamy wyznaczony najdłuższy wspólny podłańcuch.
Tak określony algorytm znajdowania najdłuższego wspólnego podciągu posiada sześcienną klasę złożoności obliczeniowej O(m2 × n), gdzie m jest długością łańcucha s1, a n jest długością łańcucha s2.
Przykład:
Wyszukać najdłuższy wspólny podłańcuch dla:
s1
= AAABBA
s2 = ABAABBAAA
| Lp. | Kolejne dopasowania s2 do s1 | Najdłuższy wspólny podłańcuch |
| 1. |
A A A B B A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A |
AAA |
| 2. |
A A A B B A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A |
AABBA |
| 3. |
A A A B B A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A |
ABBA |
| 4. |
A A A B B A A B A A B B A A A A B A A B B A A A A B A A B B A A A |
BBA |
| 5. |
A A A B B A A B A A B B A A A A B A A B B A A A A B A A B B A A A |
BA |
| 6. |
A A A B B A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A A B A A B B A A A |
A |
K01: m ← |s1| ; obliczamy długość łańcucha s1 K02: n ← |s2| ; obliczamy długość łańcucha s2 K03: s1 ← wartownik1+s1+wartownik1 ; dodajemy wartownika do s1 K04: s2 ← wartownik2+s2+wartownik2 ; dodajemy innego wartownika do s2 K05: lmax ← 0 ; zerujemy długość podłańcucha K06: Dla i = 1, 2, …, m: wykonuj kroki K07…K14 K07: Dla j = 1, 2, …, n: wykonuj kroki K08…K14 K08: Jeśli s1[i] ≠ s2[j], ; szukamy zgodnego znaku w s1 i s2 to następny obieg pętli K07 K09: lm ← 1 ; ustawiamy wstępną długość podłańcucha K10: Dopóki s1[i+lm] = s2[j+lm]: ; rozszerzamy podciąg w prawo wykonuj lm ← lm+1 K11: Jeśli lm ≤ lmax, ; sprawdzamy, czy podłańcuch jest to następny obieg pętli K07 ; dłuższy od zapamiętanego K12 lmax ← lm ; jeśli tak, zapamiętujemy go K13: p1 ← i-1 ; pozycja skorygowana z uwagi na strażnika K14: p2 ← j-1 ; pozycja skorygowana z uwagi na strażnika K15: Usuń wartowników z s1 i s2 ; przywracamy stan s1 i s2 K16: Zakończ z wynikiem lmax, p1, p2
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
| Program generuje dwa losowe łańcuchy po 40 znaków zbudowane z liter A i B. Wyszukuje w nich najdłuższy wspólny podłańcuch i wypisuje go odpowiednio pozycjonując łańcuchy względem siebie i wyznaczonego podłańcucha. Jeśli łańcuchy nie posiadają wspólnego podłańcucha, wypisywane jest słowo BRAK. |
Pascal// Wyszukiwanie najdłuższego podłańcucha
// Data: 10.07.2008
// (C)2020 mgr Jerzy Wałaszek
//--------------------------------------
program prg;
var
s1, s2 : ansistring;
i, j, p1, p2, lm, lmax : integer;
begin
randomize;
// generujemy łańcuchy s1 i s2
s1 := ''; s2 := '';
for i := 1 to 40 do
begin
s1 := s1+char(65+random(2));
s2 := s2+char(65+random(2));
end;
// wypisujemy łańcuchy s1 i s2
writeln('s1 = ', s1);
writeln('s2 = ', s2);
// szukamy najdłuższego wspólnego podłańcucha
s1 := '$'+s1+'$'; // dodajemy wartowników do s1
s2 := '#'+s2+'#'; // dodajemy wartowników do s2
lmax := 0;
for i := 2 to 41 do
for j := 2 to 41 do
if s1[i] = s2[j] then
begin
lm := 1;
while s1[i+lm] = s2[j+lm] do
inc(lm);
if lm > lmax then
begin
lmax := lm;
p1 := i-1;
p2 := j-1;
end;
end;
s1 := copy(s1, 2, 40); // usuwamy wartowników z s1
s2 := copy(s2, 2, 40); // usuwamy wartowników z s2
// prezentujemy wyniki
writeln;
if lmax = 0 then writeln('BRAK')
else
begin
repeat
if p1 > p2 then
begin
s2 := ' '+s2;
inc(p2);
end
else if p2 > p1 then
begin
s1 := ' '+s1;
inc(p1);
end;
until p1 = p2;
writeln(s1);
for i := 1 to p1-1 do write(' ');
writeln(copy(s1, p1, lmax), ' : ', lmax);
writeln(s2);
end;
end. |
C++// Wyszukiwanie najdłuższego podłańcucha
// Data: 10.07.2008
// (C)2020 mgr Jerzy Wałaszek
//--------------------------------------
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
string s1, s2;
int i, j, p1, p2, lm, lmax;
srand(time(NULL));
// generujemy łańcuchy s1 i s2
s1 = ""; s2 = "";
for(i = 0; i < 40; i++)
{
s1 += 65+rand() % 2;
s2 += 65+rand() % 2;
}
// wypisujemy łańcuchy s1 i s2
cout << "s1 = " << s1 << endl
<< "s2 = " << s2 << endl;
// szukamy najdłuższego wspólnego podłańcucha
s1 = "$"+s1+"$"; // dodajemy wartowników do s1
s2 = "#"+s2+"#"; // dodajemy wartowników do s2
lmax = 0;
for(i = 1; i <= 40; i++)
for(j = 1; j <= 40; j++)
if(s1[i] == s2[j])
{
lm = 1;
while(s1[i+lm] == s2[j+lm]) lm++;
if(lm > lmax)
{
lmax = lm; p1 = i-1; p2 = j-1;
}
}
s1 = s1.substr(1, 40); // usuwamy wartowników z s1
s2 = s2.substr(1, 40); // usuwamy wartowników z s2
// prezentujemy wyniki
cout << endl;
if(lmax == 0) cout << "BRAK\n";
else
{
do
{
if(p1 > p2)
{
s2 = " "+s2; p2++;
}
else if(p2 > p1)
{
s1 = " "+s1; p1++;
}
} while(p1 != p2);
cout << s1 << endl;
for(i = 0; i < p1; i++)
cout << " ";
cout << s1.substr(p1, lmax)
<< ": " << lmax
<< endl
<< s2 << endl;
}
return 0;
} |
Basic' Wyszukiwanie najdłuższego podłańcucha
' Data: 10.07.2008
' (C)2020 mgr Jerzy Wałaszek
'--------------------------------------
Dim As String s1, s2
Dim As Integer i, j, p1, p2, lm, lmax
Randomize
' generujemy łańcuchy s1 i s2
s1 = "": s2 = ""
For i = 1 To 40
s1 += Chr(65+Cint(Rnd))
s2 += Chr(65+Cint(Rnd))
Next
' wypisujemy łańcuchy s1 i s2
Print "s1 = ";s1
Print "s2 = ";s2
' szukamy najdłuższego wspólnego podłańcucha
s1 = "$"+s1+"$" ' dodajemy wartowników do s1
s2 = "#"+s2+"#" ' dodajemy wartowników do s2
lmax = 0
For i = 2 To 41
For j = 2 To 41
If Mid(s1, i, 1) = Mid(s2, j, 1) Then
lm = 1
While Mid(s1, i+lm, 1) = Mid(s2, j+lm, 1)
lm += 1
Wend
If lm > lmax Then
lmax = lm
p1 = i-1
p2 = j-1
End If
End If
Next
Next
s1 = Mid(s1, 2, 40) ' usuwamy wartowników z s1
s2 = Mid(s2, 2, 40) ' usuwamy wartowników z s2
' prezentujemy wyniki
Print
If lmax = 0 Then
Print "BRAK"
Else
Do
If p1 > p2 Then
s2 = " "+s2: p2 += 1
Elseif p2 > p1 Then
s1 = " "+s1: p1 += 1
End If
Loop Until p1 = p2
Print s1
For i = 1 To p1-1
Print " ";
Next
Print Mid(s1, p1, lmax);": ";lmax
Print s2
End If
End |
Python
(dodatek)# Wyszukiwanie najdłuższego podłańcucha
# Data: 15.03.2024
# (C)2024 mgr Jerzy Wałaszek
#--------------------------------------
import random
p1,p2 = 0, 0
# generujemy łańcuchy s1 i s2
s1, s2 = "", ""
for i in range(40):
s1 += chr(random.randrange(65, 67))
s2 += chr(random.randrange(65, 67))
# wypisujemy łańcuchy s1 i s2
print("s1 = %s\ns2 = %s" % (s1, s2))
# szukamy najdłuższego wspólnego podłańcucha
s1 = "$"+s1+"$" # dodajemy wartowników do s1
s2 = "#"+s2+"#" # dodajemy wartowników do s2
lmax = 0
for i in range(1, 41):
for j in range(1, 41):
if s1[i] == s2[j]:
lm = 1
while s1[i+lm] == s2[j+lm]:
lm += 1
if lm > lmax:
lmax = lm
p1, p2 = i-1, j-1
s1 = s1[1:40] # usuwamy wartowników z s1
s2 = s2[1:40] # usuwamy wartowników z s2
# prezentujemy wyniki
print()
if not lmax:
print("BRAK")
else:
while True:
if p1 > p2:
s2 = " "+s2
p2 += 1
elif p2 > p1:
s1 = " "+s1
p1 += 1
if p1 == p2:
break
print(s1)
for i in range(p1):
print(" ", end="")
print(s1[p1:p1+lmax], ":", lmax)
print(s2)
|
| Wynik: |
s1 = BBABABBABBBBABBAABAABBBAAAABABBAAAAABBBB
s2 = AAAABBBBBBBAAAABBBABBABBABBAAABAAABBBABB
BBABABBABBBBABBAABAABBBAAAABABBAAAAABBB
BBBAAAAB : 8
AAAABBBBBBBAAAABBBABBABBABBAAABAAABBBAB
|
JavaScript<html>
<head>
<title>
Najdłuższy
wspólny
podłańcuch
</title>
</head>
<body>
<div style="overflow-x: auto;"
align="center">
<table
border="0"
cellpadding="4"
style="border-collapse:
collapse">
<tr>
<td nowrap>
<form
name="frm"
style="text-align: center;
background-color:
#E7E7DA">
<b>
Wyszukiwanie najdłuższego
<br>
wspólnego podłańcucha
</b><br/>
(C)2026 mgr
Jerzy Wałaszek
<hr>
<input
type="button"
value="Wykonaj"
name="B1"
onclick="main();">
<hr>
<b>Wynik:</b>
<div
align="center"
class="small">
<table
border="0"
cellpadding="0"
style="border-collapse:
collapse">
<tr>
<td
valign="top"
style="text-align:
left">
<pre id="out">.</pre>
</td>
</tr>
</table>
</div>
</form>
</td>
</tr>
</table>
</div>
<script type=text/javascript
language=javascript>
// Wyszukiwanie najdłuższego
// podłańcucha
// Data: 10.07.2008
// (C)2008 mgr Jerzy Wałaszek
//---------------------------
function main()
{
var s1,s2,ss,i,j,ps1,ps2,
pmax1,pmax2,lm,lmax,tx;
// generujemy
// łańcuchy s1 i s2
s1 = "";
s2 = "";
for(i = 0; i < 40; i++)
{
s1 += String.fromCharCode(
65 + Math.floor(
Math.random() * 2));
s2 += String.fromCharCode(
65 + Math.floor(
Math.random() * 2));
}
// wypisujemy
// łańcuchy s1 i s2
tx = "s<sub>1</sub> = " +
s1 + "<br/>s<sub>2</sub> = " +
s2 + "<br/>";
// szukamy najdłuższego
// wspólnego podłańcucha
// dodajemy wartowników do s1
s1 = "$" + s1 + "$";
// dodajemy wartowników do s2
s2 = "#" + s2 + "#";
lmax = 0;
for(i = 1; i <= 40; i++)
for(j = 1; j <= 40; j++)
if(s1.charAt(i) ==
s2.charAt(j))
{
lm = 1;
ps1 = i;
ps2 = j;
while(s1.charAt(ps1 + lm) ==
s2.charAt(ps2 + lm))
lm++;
while(s1.charAt(ps1 - 1) ==
s2.charAt(ps2 - 1))
{
lm++;
ps1--;
ps2--;
}
if(lm > lmax)
{
lmax = lm;
pmax1 = ps1 - 1;
pmax2 = ps2 - 1;
}
}
// usuwamy strażników z s1
s1 = s1.substr(1, 40);
// usuwamy strażników z s2
s2 = s2.substr(1, 40);
// prezentujemy wyniki
tx += "<br/>";
if(lmax == 0)
tx += "<b>BRAK</b>";
else
{
ss = s1.substr(pmax1, lmax);
do
{
if(pmax1 > pmax2)
{
s2 = " " + s2;
pmax2++;
}
else if(pmax2 > pmax1)
{
s1 = " " + s1;
pmax1++;
}
} while(pmax1 != pmax2);
tx += s1 + "<br/>";
for(i = 0; i < pmax1; i++)
tx += " ";
tx += ss + " : " + lmax +
"<br/>" + s2;
}
document.getElementById("out")
.innerHTML = "<b>" + tx + "</b>";
}
</script>
</body>
</html>
|
Drugie rozwiązanie wykorzystuje programowanie dynamiczne, gdzie zapamiętujemy w osobnej tablicy długości pasujących podłańcuchów w obu łańcuchach s1 i s2. Dzięki temu klasa złożoności obliczeniowej algorytmu spada do O(m×n). Algorytm dynamiczny wymaga dodatkowej pamięci rozmiaru O(m×n) na zapamiętywanie długości podłańcuchów. Zasada działania jest następująca:
Oznaczmy przez L[i+1, j+1] największą długość (ang. length) wspólnego podłańcucha kończącego się na pozycjach s1[i] oraz s2[j]. Długość tę wyznaczamy z długości L[i, j] w następujący sposób:
Jeśli s1[i] ≠ s2[j], to L[i+1, j+1] ← 0 Jeśli s1[i] = s2[j], to L[i+1, j+1] ← 1+L[i, j]
Wynika z tego, iż długość wspólnego podłańcucha rośnie o 1, jeśli znaki na pozycjach i oraz j w obu łańcuchach są zgodne. W przeciwnym razie długość zeruje się. Wyliczone długości są zapamiętywane w tablicy L, dzięki czemu w kolejnych obiegach pętli nie musimy ich wyznaczać.
K01: m ← |s1| ; obliczamy długość łańcucha s1 K02: n ← |s2| ; obliczamy długość łańcucha s2 K03: Utwórz tablicę L[m+1, n+1] K04: Dla i = 0, 1, …, m: ; zerujemy pierwszą kolumnę tablicy L wykonuj L[i, 0] ← 0 K05: Dla j = 0, 1, …, n: ; zerujemy pierwszy wiersz tablicy L wykonuj L[0, j] ← 0 K06: lmax ← 0 ; zerujemy największą długość wspólnego podłańcucha K07: Dla i = 0, 1, …, m-1: ; przebiegamy przez kolejne znaki s1 wykonuj kroki K08…K16 K08: Dla j = 0, 1, …, n-1: ; przebiegamy przez kolejne znaki s2 wykonuj kroki K09…K16 K09: Jeśli s1[i] = s2[j], ; sprawdzamy równość znaków w łańcuchach to idź do kroku K12 K10: L[i+1, j+1] ← 0 ; znaki są różne, długość zerujemy K11: Następny obieg pętli K07 K12: L[i+1, j+1] ← 1+L[i, j] ; obliczamy nową długość wspólnego podłańcucha K13: Jeśli L[i+1, j+1] ≤ lmax, ; sprawdzamy, czy jest to najdłuższy podłańcuch to następny obieg pętli K07 K14: lmax ← L[i+1, j+1] ; zapamiętujemy długość wspólnego podłańcucha K15: p1 ← i-lmax+1 ; oraz jego pozycję w s1 K16 p2 ← j-lmax+1 ; i w s2 K17: Zakończ z wynikiem lmax, p1, p2
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
| Program generuje dwa losowe łańcuchy po 40 znaków zbudowane z liter A i B. Wyszukuje w nich najdłuższy wspólny podłańcuch i wypisuje go odpowiednio pozycjonując łańcuchy względem siebie i wyznaczonego podłańcucha. Jeśli łańcuchy nie posiadają wspólnego podłańcucha, wypisywane jest słowo BRAK. |
Pascal// Wyszukiwanie najdłuższego podłańcucha
// Data: 16.07.2008
// (C)2020 mgr Jerzy Wałaszek
//--------------------------------------
program prg;
var
s1, s2 : ansistring;
i, j, p1, p2, lmax : integer;
L : array [0..40, 0..40] of integer;
begin
randomize;
// generujemy łańcuchy s1 i s2
s1 := ''; s2 := '';
for i := 1 to 40 do
begin
s1 := s1+char(65+random(2));
s2 := s2+char(65+random(2));
end;
// wypisujemy łańcuchy s1 i s2
writeln('s1 = ', s1);
writeln('s2 = ', s2);
// szukamy najdłuższego wspólnego podłańcucha
for i := 0 to 40 do
begin
L[i, 0] := 0;
L[0, i] := 0;
end;
lmax := 0;
for i := 1 to 40 do
for j := 1 to 40 do
if s1[i] <> s2[j] then
L[i, j] := 0
else
begin
L[i, j] := 1+L[i-1, j-1];
if L[i, j] > lmax then
begin
lmax := L[i, j];
p1 := i-lmax+1;
p2 := j-lmax+1;
end;
end;
// prezentujemy wyniki
writeln;
if lmax = 0 then writeln('BRAK')
else
begin
repeat
if p1 > p2 then
begin
s2 := ' '+s2; inc(p2);
end
else if p2 > p1 then
begin
s1 := ' '+s1; inc(p1);
end;
until p1 = p2;
writeln(s1);
for i := 1 to p1-1 do
write(' ');
writeln(copy(s1, p1, lmax), ' : ', lmax);
writeln(s2);
end;
end. |
C++// Wyszukiwanie najdłuższego podłańcucha
// Data: 16.07.2008
// (C)2020 mgr Jerzy Wałaszek
//--------------------------------------
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
string s1, s2;
int i, j, p1, p2, lmax, L[41][41];
srand(time(NULL));
// generujemy łańcuchy s1 i s2
s1 = ""; s2 = "";
for(i = 0; i < 40; i++)
{
s1 += 65+rand() % 2;
s2 += 65+rand() % 2;
}
// wypisujemy łańcuchy s1 i s2
cout << "s1 = " << s1 << endl
<< "s2 = " << s2 << endl;
// szukamy najdłuższego wspólnego podłańcucha
for(i = 0; i <= 40; i++)
L[i][0] = L[0][i] = 0;
lmax = 0;
for(i = 0; i < 40; i++)
for(j = 0; j < 40; j++)
if(s1[i] != s2[j]) L[i+1][j+1] = 0;
else
{
L[i+1][j+1] = 1+L[i][j];
if(L[i+1][j+1] > lmax)
{
lmax = L[i+1][j+1];
p1 = i-lmax+1;
p2 = j-lmax+1;
}
}
// prezentujemy wyniki
cout << endl;
if(lmax == 0) cout << "BRAK\n";
else
{
do
{
if(p1 > p2)
{
s2 = " "+s2;
p2++;
}
else if(p2 > p1)
{
s1 = " "+s1;
p1++;
}
} while(p1 != p2);
cout << s1 << endl;
for(i = 0; i < p1; i++)
cout << " ";
cout << s1.substr(p1, lmax) << " : "
<< lmax << endl
<< s2 << endl;
}
return 0;
} |
Basic' Wyszukiwanie najdłuższego podłańcucha ' Data: 16.07.2008 ' (C)2020 mgr Jerzy Wałaszek '-------------------------------------- Dim As String s1, s2 Dim As Integer i, j, p1, p2, lmax, L(40, 40) Randomize ' generujemy łańcuchy s1 i s2 s1 = "": s2 = "" For i = 1 To 40 s1 += Chr(65+Cint(Rnd)) s2 += Chr(65+Cint(Rnd)) Next ' wypisujemy łańcuchy s1 i s2 Print "s1 = ";s1 Print "s2 = ";s2 ' szukamy najdłuższego wspólnego podłańcucha For i = 0 To 40 L(i, 0) = 0 L(0, i) = 0 Next lmax = 0 For i = 1 To 40 For j = 1 To 40 If Mid(s1, i, 1) <> Mid(s2, j, 1) Then L(i, j) = 0 Else L(i, j) = 1+L(i-1, j-1) If L(i, j) > lmax Then lmax = L(i, j) p1 = i-lmax+1 p2 = j-lmax+1 End If End If Next Next ' prezentujemy wyniki Print If lmax = 0 Then Print "BRAK" Else Do If p1 > p2 Then s2 = " "+s2: p2 += 1 Elseif p2 > p1 Then s1 = " "+s1: p1 += 1 End If Loop Until p1 = p2 Print s1 For i = 1 To p1-1 Print " "; Next Print Mid(s1, p1, lmax);" : ";lmax Print s2 End If End |
Python
(dodatek)# Wyszukiwanie najdłuższego podłańcucha
# Data: 16.03.2024
# (C)2024 mgr Jerzy Wałaszek
#--------------------------------------
import random
N = 40 # Długość łańcuchów
p1, p2 = 0, 0
# konstruujemy tablicę dwuwymiarową
t_l = [[0 for j in range(N+1)] for i in range(41)]
# generujemy łańcuchy s1 i s2
s1 = ""
s2 = ""
for i in range(N):
s1 += chr(random.randrange(65, 67))
s2 += chr(random.randrange(65, 67))
# wypisujemy łańcuchy s1 i s2
print("s1 =", s1)
print("s2 =", s2)
# szukamy najdłuższego wspólnego podłańcucha
lmax = 0
for i in range(40):
for j in range(40):
if s1[i] != s2[j]:
t_l[i+1][j+1] = 0
else:
t_l[i+1][j+1] = 1+t_l[i][j]
if t_l[i+1][j+1] > lmax:
lmax = t_l[i+1][j+1]
p1 = i-lmax+1
p2 = j-lmax+1
# prezentujemy wyniki
print()
if lmax == 0: print("BRAK")
else:
while True:
if p1 > p2:
s2 = " "+s2
p2 += 1
elif p2 > p1:
s1 = " "+s1
p1 += 1
else: break
print(s1)
for i in range(p1):
print(" ", end="")
print(s1[p1:p1+lmax], ":", lmax)
print(s2)
print()
|
Zwróć uwagę, iż w prezentowanym powyżej algorytmie stosujemy dwuwymiarową tablicę L[m×n]. Tymczasem w tablicy tej wykorzystywane są tylko dwa wiersze – i-ty oraz (i-1)-szy. Algorytm możemy tak zmodyfikować, aby wymiar tablicy spadł do L[2×n]. Zmniejszy to zapotrzebowanie na pamięć do rozmiaru O(n), zamiast O(m×n).
K01: m ← |s1| ; obliczamy długość łańcucha s1 K02: n ← |s2| ; obliczamy długość łańcucha s2 K03: Twórz tablicę L[2, n+1] K04: Dla j = 0, 1, …, n: ; zerujemy pierwszy wiersz tablicy L wykonuj L[0, j] ← 0 K05: lmax ← 0 ; zerujemy największą długość wspólnego podłańcucha K06: Dla i = 0, 1, …, m-1: ; przebiegamy przez kolejne znaki s1 wykonuj kroki K07…K16 K07: Dla j = 0, 1, …, n-1: ; przebiegamy przez kolejne znaki s2 wykonuj kroki K08…K15 K08: Jeśli s1[i] = s2[j], ; sprawdzamy równość znaków to idź do kroku K11 K09: L[1, j+1] ← 0 ; znaki są różne, długość zerujemy K10: Następny obieg pętli K06 K11: L[1, j+1] ← 1+L[0, j] ; obliczamy nową długość wspólnego podłańcucha K12: Jeśli L[1, j+1] ≤ lmax, ; sprawdzamy, czy jest to najdłuższy podłańcuch to następny obieg pętli K06 K13: lmax ← L[1, j+1] ; zapamiętujemy długość wspólnego podłańcucha K14: p1 ← i-lmax+1 ; oraz jego pozycję w s1 K15: p2 ← j-lmax+1 ; i w s2 K16: Dla j = 0, 1, …, n: ; przepisujemy wiersz 1 do wiersza 0 tablicy L wykonuj L[0, j] ← L[1, j] K17: Zakończ z wynikiem lmax, p1, p2
Zmodyfikowanie przykładowych programów wg nowego algorytmu pozostawiam czytelnikowi jako proste ćwiczenie w programowaniu. A może wymyślisz sposób przełączania wierszy tablicy L bez konieczności ich przepisywania – zastanów się nad dwoma dodatkowymi zmiennymi indeksującymi wiersze tej tablicy.
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.