• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Najdłuższy palindrom w stringu

Object Storage Arubacloud
+1 głos
286 wizyt
pytanie zadane 26 czerwca 2023 w C i C++ przez Szyszka Gaduła (3,490 p.)

Witam.

Mam takie zadanie: Dla podanego stringa s zwróć najdłuższy palindromiczny string zawarty w s.

Zrobiłem rozwiązanie O(n^3) gdzie n to długość stringa s, nawet zaliczyło mi to rozwiązanie, ale patrząc na statystyki:

Widać że te złożoność da się mocno poprawić. Widziałem jedno rozwiązanie używające programowania dynamicznego, ale też było O(n^2). Więc jak można to inaczej zrobić?

To mój obecny kod:

bool is_palindromic(const std::string& s, const size_t& start, const size_t& end) {
	for (size_t i = start, j = end; i <= j; i++, j--) {
		if (s[i] != s[j])
			return false;
	}

	return true;
}

std::string longestPalindrome(std::string s) {
	std::pair<uint32_t, uint32_t> max = { 0,0 };
	for (uint32_t i = 0; i < s.size(); i++) {
		uint32_t solution = 0;
		for (uint32_t j = i + 1; j < s.size(); j++) {
			if (is_palindromic(s, i, j)) {
				solution = j;
			}
		}

		if (i < solution && solution - i > max.second - max.first)
			max = { i, solution };
	}

	std::string result = "";
	for (uint32_t i = max.first; i <= max.second; i++)
		result += s[i];

	return result;
}

 

1 odpowiedź

+2 głosów
odpowiedź 26 czerwca 2023 przez jankustosz1 Nałogowiec (35,880 p.)
wybrane 27 czerwca 2023 przez Szyszka
 
Najlepsza
Widzę rozwiązanie w O(n log n)

Robisz tablicę haszy prefixów tablicy oraz tablicę haszy prefixów odwróconej tablicy.

Dzięki temu możesz w O(1) sprawdzić czy przedział od a do b jest palindromem po prostu porównując czy pierwszy hasz jest równy drugiemu.

Gdyby wziąć każdy początek i koniec byłoby O(n^2). Można jednak zauważyć, że jak ciąg o danym środku jest palindromem o długości k to będzie także palindromem dla długości k-2 i mniejszych. Można więc wykorzystać binsearcha w następujący sposób:
Przechodzimy po każdym elemencie w tablicy i zakładamy że jest środkiem palindromu i próbujemy binsearchem zgadnąć jak długim jest palindromem (zajmie do czas O(log n) dla pojedynczego elementu). Analogicznie można zrobić dla panlidromów z parzystymi długościami. Złożoność (n log n)
komentarz 26 czerwca 2023 przez Szyszka Gaduła (3,490 p.)
Co znaczy "tablica haszy prefixów"? Mam brać hash dla każdego możliwego podstringa i dla jego odwrotności? Na pewno nie rozumiem, bo to już by było O(n^2). I też nie rozumiem o co chodzi z tym, że jeśli "ciąg o danym środku jest palindromem o długości k to będzie także palindromem dla dlugości k-2 i mniejszych", np. weźmy wyraz "kajak", odejmę np. 2, będzie "kaj" i to przecież nie jest palindrom. Właściwie to chyba nic nie zrozumiałem :/
komentarz 26 czerwca 2023 przez infinityhost Użytkownik (780 p.)
dla każdego elementu w tablicy uruchamiaj pętlę sprawdzającą elementy +1 -1, aż 1) nie dojdzie do końca tablicy, 2) dokąd element -1 +1 są takie same. jak pętla się uruchomi chociaż raz dodawaj do tablicy pomocniczej aktualny rozmiar
komentarz 26 czerwca 2023 przez adrian17 Ekspert (344,860 p.)

Na pewno nie rozumiem, bo to już by było O(n^2).

Nikt nie powiedział że musisz dla każdego zakresu wołać substring() i liczyć od zera hash tego substringa. Wystarczy że podczas iteracji będziesz na bieżąco budował hash dodając jedynie kolejne znaki.

komentarz 26 czerwca 2023 przez jankustosz1 Nałogowiec (35,880 p.)

Chodzi o haszowanie jak w algorytmie Karpa-Rabina: https://eduinf.waw.pl/inf/alg/001_search/0052.php

Chcąc sprawdzić w czasie O(1) czy tekst od i do i+k jest palidromem zrobiłbyś coś w tym rodzaju: (może nie zgadzać się wyliczenie indeksu, sprawdź to sobie)

long long h1 = hash[i+k] - hash[i-1];
long long h2 = hash[n-(i+1)] - hash[n-(i+k+2)];
if(h1 == h2)
   cout << "ciąg jest palindromem";

Jak weźmiemy środek palidroma kajak i odejmiemy tyle samo znaków z lewej co z prawej to dalej jest to palindrom - o to chodziło.

 

Podobne pytania

0 głosów
2 odpowiedzi 373 wizyt
pytanie zadane 19 stycznia 2020 w C i C++ przez Piotrek1122 Nowicjusz (140 p.)
0 głosów
1 odpowiedź 244 wizyt
pytanie zadane 7 sierpnia 2022 w C i C++ przez Noizz00 Użytkownik (910 p.)
0 głosów
2 odpowiedzi 829 wizyt
pytanie zadane 29 stycznia 2017 w C i C++ przez Natalia Cierpiał Nowicjusz (120 p.)

92,579 zapytań

141,429 odpowiedzi

319,657 komentarzy

61,962 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...