[C++ implementiert einen Mustervergleichsalgorithmus für Zeichenfolgen]

Vorwort

Bisher wurden in dieser Spalte nacheinander die Speichermethoden von Datenstrukturen wie sequentiellen Listen, verknüpften Listen, Arrays, Stapeln, Warteschlangen und Binärbäumen sowie wichtige Operationsimplementierungen vorgestellt. Als nächstes wird in dieser Ausgabe die Speichermethode und Anwendung von Zeichenfolgen erläutert: der Mustervergleichsalgorithmus von Zeichenfolgen

Text

1. Zeichenfolge

String, kurz für String, ist eine endliche Folge von null oder mehr Zeichen. Im Allgemeinen aufgezeichnet als:

  • S = 'A1A2A3...An' (n>=0)
    Teilzeichenfolge: Eine Teilfolge, die aus einer beliebigen Anzahl verbundener Zeichen in einer Zeichenfolge besteht, wird als Teilzeichenfolge der Zeichenfolge bezeichnet.
    Hauptzeichenfolge: Die Zeichenfolge, die Teilzeichenfolgen enthält, wird als Hauptzeichenfolge der Zeichenfolge bezeichnet.

2. Speicherstruktur

Die Speicherstruktur einer Zeichenfolge kann auf drei Arten dargestellt werden:

  • Sequentielle Speicherdarstellung mit fester Länge (ähnlich dem Array mit fester Länge)
  • Darstellung des Heap-Zuordnungsspeichers (dynamische Anwendung)
  • Darstellung des Blockchain-Speichers (ähnlich dem Kettenspeicher)

3. String-Musterabgleich

Der Teilstring-Positionierungsvorgang wird üblicherweise als String-Pattern-Matching bezeichnet und sucht nach der Position des Teilstrings (auch Musterstring genannt) im Hauptstring.

//定长顺序存储结构
typedef struct SString{
    
    
   int length;
   char ch[255];
   SString(int len,char c[]){
    
    
       length = len;
       int i = 0;
       while(c[i] != '\0')
       {
    
    
           ch[i] = c[i];
           i++;
       }
   }
};

a. Einfacher Mustervergleichsalgorithmus

Idee: Lösen Sie heftig, vergleichen Sie die Elemente zweier Zeichenfolgen durch Schleifen. Wenn im Hauptstring ein vollständiger Teilstring gefunden wird, wird der Anfangsindex des Teilstrings zurückgegeben. Andernfalls wird -1 zurückgegeben.
Die schlechteste Zeitkomplexität ist: O(mn) m, n ist die Länge der beiden Zeichenfolgen.

int MyString::IndexSubstr(SString string1, SString string2)
{
    
    
    if(string1.length <=0)
    {
    
    
        return -1;
    }
    int i = 0,j = 0;
    while(i<string1.length && j<string2.length)
    {
    
    
        char _ch1 = string1.ch[i];
        char _ch2 = string2.ch[j];
        if(_ch1 != _ch2)
        {
    
    
            i ++;
            j = 0;
        }
        else
        {
    
    
            i ++;
            j ++;
            if(j == string2.length)
            {
    
    
                return i-string2.length;
            }
        }

    }
    return -1;
}

b. KMP-Algorithmus zum Vergleichen von Zeichenfolgenmustern

Gedanke:Im Vergleich zum einfachen Mustervergleichsalgorithmus optimiert der KMP-Algorithmus die Verarbeitung, wenn der Musterzeichenfolgenvergleich fehlschlägt.
Wenn im einfachen Mustervergleichsalgorithmus der Zeichenfolgenvergleich fehlschlägt, wird der Zeiger von j direkt an die erste Elementposition der Zeichenfolge zurückgegeben. Zu diesem Zeitpunkt wird der Fall, dass die Teilzeichenfolge wiederholte Präfixe enthält, nicht berücksichtigt.
Fügen Sie hier eine Bildbeschreibung ein

//计算模式串失配后,应当跳转比较元素下标
std::vector<int> MyString::computeNext(SString pattern) {
    
    
    int m = pattern.length;
    std::vector<int> next(m, 0);
    int i = 1;
    int j = 0;

    while (i < m) {
    
    
        if (pattern.ch[i] == pattern.ch[j]) {
    
    
            j++;
            next[i] = j;
            i++;
        } else {
    
    
            if (j != 0) {
    
    
                j = next[j - 1];
            } else {
    
    
                next[i] = 0;
                i++;
            }
        }
    }

    return next;
}
//KMP算法,将所有与模式串匹配的下标存储动态数组
std::vector<int> MyString::KMP(SString text, SString pattern) {
    
    
    std::vector<int> next = computeNext(pattern);
    std::vector<int> matches;
    int n = text.length;
    int m = pattern.length;
    int i = 0;
    int j = 0;

    while (i < n) {
    
    
        if (pattern.ch[j] == text.ch[i]) {
    
    
            i++;
            j++;
        }

        if (j == m) {
    
    
            matches.push_back(i - j);
            j = next[j - 1];
        } else if (i < n && pattern.ch[j] != text.ch[i]) {
    
    
            if (j != 0) {
    
    
                j = next[j - 1];
            } else {
    
    
                i++;
            }
        }
    }

    return matches;
}

c. Optimierung des KMP-Algorithmus

Für die kontinuierlich wiederholten Elemente, die in der Musterzeichenfolge erscheinen, erfolgt im KMP-Algorithmus immer noch ein wiederholter Zugriff auf unnötige Elemente. In dieser Hinsicht können wir den KMP-Algorithmus weiter optimieren.
Follow-up-Updates. . .

Acho que você gosta

Origin blog.csdn.net/wddkxg/article/details/131520368
Recomendado
Clasificación