Nájdite v Jave podreťazce, ktoré sú palindrómmi

1. Prehľad

V tomto rýchlom výučbe si ukážeme rôzne prístupy k nájdenie všetkých podreťazcov v danom reťazci, ktoré sú palindrómy. Zaznamenáme tiež časovú zložitosť každého prístupu.

2. Priblíženie hrubou silou

V tomto prístupe jednoducho vykonáme iteráciu nad vstupným reťazcom, aby sme našli všetky podreťazce. Zároveň skontrolujeme, či je podreťazec palindróm alebo nie:

public Set findAllPalindromesUsingBruteForceApproach (reťazcový vstup) {Set palindromes = new HashSet (); pre (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)); }}} vratit palindromy; }

Vo vyššie uvedenom príklade iba porovnáme podreťazec s jeho reverzom, aby sme zistili, či ide o palindróm:

private boolean isPalindrome (String input) {StringBuilder plain = new StringBuilder (input); StringBuilder reverse = plain.reverse (); return (reverse.toString ()). equals (vstup); }

Samozrejme si môžeme ľahko zvoliť z niekoľkých ďalších prístupov.

Časová zložitosť tohto prístupu je O (n ^ 3). Aj keď to môže byť prijateľné pre malé vstupné reťazce, pri kontrole palindrómov vo veľkých objemoch textu budeme potrebovať efektívnejší prístup.

3. Centralizačný prístup

Myšlienka centralizovaného prístupu je: zvážte každú postavu ako otočnú čiarku a rozbaľte sa oboma smermi, aby ste našli palindrómy.

Rozbalíme to, iba ak sa znaky na ľavej a pravej strane zhodujú, čím sa reťazec kvalifikuje ako palindróm. Inak pokračujeme k ďalšiemu znaku.

Pozrime sa na krátku ukážku, v ktorej budeme každý znak považovať za stred palindrómu:

public Set findAllPalindromesUsingCenter (reťazcový vstup) {Set palindromes = new HashSet (); pre (int i = 0; i <input.length (); i ++) {palindromes.addAll (findPalindromes (input, i, i + 1)); palindromes.addAll (findPalindromes (vstup, i, i)); } návratové palindrómy; }

V rámci slučky vyššie sa rozširujeme v oboch smeroch, aby sme získali množinu všetkých palindrómov vycentrovaných na každú pozíciu. Palindrómy párnej aj nepárnej dĺžky nájdeme volaním metódy findPalindromes dvakrát v slučke:

private Set findPalindromes (String input, int low, int high) {Set result = new HashSet (); while (low> = 0 && high <input.length () && input.charAt (low) == input.charAt (high)) {result.add (input.substring (low, high + 1)); nízka--; vysoký ++; } vrátiť výsledok; }

Časová zložitosť tohto prístupu je O (n ^ 2). Toto je zlepšenie oproti nášmu prístupu hrubou silou, ale môžeme to urobiť ešte lepšie, ako uvidíme v nasledujúcej časti.

4. Manacherov algoritmus

Manacherov algoritmusnájde najdlhší palindromický podreťazec v lineárnom čase. Tento algoritmus použijeme na nájdenie všetkých podreťazcov, ktoré sú palindrómmi.

Predtým, ako sa ponoríme do algoritmu, inicializujeme niekoľko premenných.

Najskôr strážime vstupný reťazec hraničným znakom na začiatku a na konci pred konverziou výsledného reťazca na pole znakov:

Reťazec formattedInput = "@" + vstup + "#"; char inputCharArr [] = formattedInput.toCharArray ();

Potom použijeme dvojrozmerné pole polomer s dvoma riadkami - jedným na uloženie dĺžok nepárnych dĺžok palindrómov a druhým na uloženie dĺžok párnych dĺžok palindrómov:

int radius [] [] = new int [2] [input.length () + 1];

Ďalej vykonáme iteráciu nad vstupným poľom, aby sme našli dĺžku palindrómu vycentrovanú na pozíciu i a túto dĺžku uložiť do polomer[][]:

Nastaviť palindromy = nový HashSet (); int max; pre (int j = 0; j <= 1; j ++) {polomer [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 ++; polomer [j] [i] = max; int k = 1; while ((polomer [j] [i - k]! = max - k) && (k <max)) {radius [j] [i + k] = Math.min (polomer [j] [i - k], max - k); k ++; } max = Math.max (max - k, 0); i + = k; }}

Nakoniec prejdeme cez pole polomer[][] na výpočet palindromických podreťazcov so stredom v každej polohe:

pre (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)); }}}

Časová zložitosť tohto prístupu je O (n).

5. Záver

V tomto rýchlom článku sme diskutovali o časovej zložitosti rôznych prístupov k hľadaniu podreťazcov, ktoré sú palindrómy.

Celý zdrojový kód príkladov je ako vždy k dispozícii na serveri GitHub.


$config[zx-auto] not found$config[zx-overlay] not found