[C++ реализует алгоритм сопоставления шаблонов для строк]

предисловие

До сих пор в этой колонке по очереди были представлены методы хранения структур данных, таких как последовательные списки, связанные списки, массивы, стеки, очереди и двоичные деревья, а также важные реализации операций. Далее в этом выпуске будут объяснены метод хранения и применение строк: алгоритм сопоставления строк с образцом.

текст

1. Строка

Строка, сокращение от string, представляет собой конечную последовательность из нуля или более символов. Обычно записывается как:

  • S = 'A1A2A3...An' (n>=0)
    Подстрока: Подпоследовательность, состоящая из любого количества связанных символов в строке, называется подстрокой строки.
    Основная строка: строка, содержащая подстроки, называется основной строкой строки.

2. Структура хранения

Структуру хранения строки можно представить тремя способами:

  • Представление последовательного хранилища фиксированной длины (аналогично массиву фиксированной длины)
  • Представление хранилища распределения кучи (динамическое приложение)
  • Представление хранилища цепочки блоков (аналогично хранилищу цепочки)

3. Сопоставление строкового шаблона

Операцию позиционирования подстроки обычно называют сопоставлением с образцом строки, которая ищет позицию подстроки (также называемой строкой шаблона) в основной строке.

//定长顺序存储结构
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++;
       }
   }
};

А. Простой алгоритм сопоставления с образцом

Идея: решить насильственно, сравнить элементы двух строк, зацикливая их. Если в основной строке найдена полная подстрока, верните начальный индекс подстроки. В противном случае возвращается -1.
Наихудшая временная сложность: O(mn) m, n — длина двух строк.

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;
}

б. Алгоритм сопоставления строкового шаблона KMP.

Мысль:По сравнению с простым алгоритмом сопоставления шаблонов алгоритм KMP оптимизирует обработку в случае сбоя сопоставления строк шаблона..
В простом алгоритме сопоставления с образцом, если сопоставление строки не удается, указатель j возвращается непосредственно в позицию первого элемента строки. В настоящее время случай, когда в подстроке присутствуют повторяющиеся префиксы, не рассматривается.
вставьте сюда описание изображения

//计算模式串失配后,应当跳转比较元素下标
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;
}

в) Оптимизация алгоритма КМП.

Для непрерывно повторяющихся элементов, появляющихся в строке шаблона, в алгоритме KMP по-прежнему происходит повторный доступ к ненужным элементам. В связи с этим мы можем и дальше продолжать оптимизировать алгоритм КМП.
Следите за обновлениями. . .

Guess you like

Origin blog.csdn.net/wddkxg/article/details/131520368
C++
Recommended