Pronađite podnizice koji su palindromi u Javi

1. Pregled

U ovom ćemo brzom vodiču proći kroz različite pristupe pronalaženje svih podnizova unutar datog niza koji su palindromi. Također ćemo primijetiti vremensku složenost svakog pristupa.

2. Pristup grube sile

U ovom ćemo pristupu jednostavno prelaziti kroz ulazni niz da bismo pronašli sve podnizove. Istodobno ćemo provjeriti je li podniz palindrom ili nije:

javni Postavi findAllPalindromesUsingBruteForceApproach (String input) {Set palindromes = new HashSet (); for (int i = 0; i <input.length (); i ++) {for (int j = i + 1; j <= input.length (); j ++) {if (isPalindrome (input.substring (i, j ))) {palindromes.add (input.substring (i, j)); }}} povratni palindromi; }

U gornjem primjeru samo uspoređujemo podniz sa njegovim reverzom kako bismo vidjeli je li palindrom:

privatni logički isPalindrome (unos niza) {StringBuilder plain = novi StringBuilder (ulaz); StringBuilder reverse = plain.reverse (); return (reverse.toString ()). jednako (ulaz); }

Naravno, lako možemo birati između nekoliko drugih pristupa.

Složenost vremena ovog pristupa je O (n ^ 3). Iako je to možda prihvatljivo za male ulazne nizove, trebat će nam učinkovitiji pristup ako provjeravamo palindrome u velikim količinama teksta.

3. Pristup centralizacije

Ideja u pristupu centralizacije je da smatrajte svaki lik stožićem i proširite se u oba smjera kako biste pronašli palindrome.

Proširit ćemo se samo ako se znakovi na lijevoj i desnoj strani podudaraju, kvalificirajući niz kao palindrom. Inače nastavljamo sa sljedećim likom.

Pogledajmo brzu demonstraciju u kojoj ćemo svaki lik smatrati središtem palindroma:

javni Postavi findAllPalindromesUsingCenter (unos niza) {Postavi palindrome = novi HashSet (); for (int i = 0; i <input.length (); i ++) {palindromes.addAll (findPalindromes (input, i, i + 1)); palindromi.addAll (findPalindromes (input, i, i)); } povratni palindromi; }

Unutar gornje petlje širimo se u oba smjera kako bismo dobili skup svih palindroma usredotočenih na svakom položaju. Pozivanjem metode pronaći ćemo palindrome i parne i neparne duljine naćiPalindrome dvaput u petlji:

private Set findPalindromes (String input, int low, int high) {Postavi rezultat = novi HashSet (); while (low> = 0 && high <input.length () && input.charAt (low) == input.charAt (high)) {result.add (input.substring (low, high + 1)); nisko--; visoka ++; } vratiti rezultat; }

Složenost vremena ovog pristupa je O (n ^ 2). Ovo je poboljšanje u odnosu na naš grubi pristup, ali možemo i bolje, kao što ćemo vidjeti u sljedećem odjeljku.

4. Manacherov algoritam

Manacherov algoritampronalazi najdužu palindromsku podniz u linearnom vremenu. Ovim ćemo algoritmom pronaći sve podnizove koji su palindromi.

Prije nego što uđemo u algoritam, inicijalizirat ćemo nekoliko varijabli.

Prvo ćemo zaštititi ulazni niz s graničnim znakom na početku i na kraju prije pretvaranja rezultirajućeg niza u niz znakova:

String formattedInput = "@" + input + "#"; char inputCharArr [] = formattedInput.toCharArray ();

Zatim ćemo upotrijebiti dvodimenzionalni niz radius s dva reda - jedan za pohranu duljina palindroma neparne duljine, a drugi za pohranu duljina palindroma parne duljine:

int radijus [] [] = novi int [2] [input.length () + 1];

Dalje, prelazit ćemo kroz ulazni niz da bismo pronašli duljinu palindroma usredotočenog na položaju ja i pohranite ovu duljinu u radius[][]:

Postavi palindrome = novi HashSet (); int max; za (int j = 0; j <= 1; j ++) {radijus [j] [0] = max = 0; int i = 1; while (i <= input.length ()) {palindromes.add (Character.toString (inputCharArr [i])); while (inputCharArr [i - max - 1] == inputCharArr [i + j + max]) max ++; polumjer [j] [i] = max; int k = 1; while ((radijus [j] [i - k]! = max - k) && (k <max)) {radijus [j] [i + k] = Math.min (radijus [j] [i - k], max - k); k ++; } max = Math.max (max - k, 0); i + = k; }}

Konačno, preći ćemo niz radius[][] za izračunavanje palindromskih podnizova usredotočenih na svakom položaju:

for (int i = 1; i <= input.length (); i ++) {for (int j = 0; j 0; max--) {palindromes.add (input.substring (i - max - 1, max + j + i - 1)); }}}

Vremenska složenost ovog pristupa je O (n).

5. Zaključak

U ovom kratkom članku razgovarali smo o vremenskoj složenosti različitih pristupa pronalaženju podnizova koji su palindromi.

Kao i uvijek, puni izvorni kod primjera dostupan je na GitHub-u.