Оглавление
предисловие
До сих пор в этой колонке по очереди были представлены методы хранения структур данных, таких как последовательные списки, связанные списки, массивы, стеки, очереди и двоичные деревья, а также важные реализации операций. Далее в этом выпуске будут объяснены метод хранения и применение строк: алгоритм сопоставления строк с образцом.
текст
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 по-прежнему происходит повторный доступ к ненужным элементам. В связи с этим мы можем и дальше продолжать оптимизировать алгоритм КМП.
Следите за обновлениями. . .