|
|||
Префикс-функцияРассмотрим строку Алгоритм вычисленияЗаметим сначала, что ![]() где
– символ строки, – символы которые нужно сравнить (префикс и суффикс могут «накладываться» друг на друга). Если же , то нужно рассмотреть префикс длины . Предположим, что это не так, то есть, что существует префикс подстроки длины , такой что и совпадающий с суффиксом длины :![]() Это невозможно, т.к. в качестве значения
мы должны были бы взять . Аналогично, если длина не подходит, то проверять нужно , и т.д.Реализация алгоритма на языке C++: std::vector<int> pf(s.size() + 1, 0);
for (int i = 2; i < (int)pf.size(); i++) {
int prefLen = pf[i - 1];
while (true) {
if (s[i - 1] == s[prefLen]) {
pf[i] = prefLen + 1;
break;
} else if (prefLen == 0) {
break;
}
prefLen = pf[prefLen];
}
}
На каждом шаге внешнего цикла значение префикс-функции увеличивается не более чем на единицу, поэтому Задача о количестве различных подстрокПриведем пример задачи, которая решается с помощью префикс-функции. Пусть Будем решать задачу с помощью динамического программирования. На каждом шаге алгоритма будем добавлять в строку по символу из ![]() где
– это префикс-функция, вычисленная для . Пусть – это длина строки . Тогда мы раз будем добавлять по символу и каждый раз заново вычислять префикс-функцию. Значит сложность алгоритма составит .Реализация решения задачи на языке C++: int nUniqueSubstrings = 0;
std::vector<int> pf(s.length() + 1, 0);
std::string currentString = "";
for (int i = 0; i < (int)s.length(); i++) {
currentString += s[i];
std::string reversedCurrentString = currentString;
std::reverse(reversedCurrentString.begin(), reversedCurrentString.end());
pf[1] = 0;
for (int j = 2; j <= i + 1; j++) {
int prefLen = pf[j - 1];
while (true) {
if (reversedCurrentString[j - 1] == reversedCurrentString[prefLen]) {
pf[j] = prefLen + 1;
break;
} else if (prefLen == 0) {
pf[j] = 0;
break;
}
prefLen = pf[prefLen];
}
}
int maxLength = 0;
for (int j = 2; j <= i + 1; j++) {
maxLength = std::max(maxLength, pf[j]);
}
nUniqueSubstrings += i + 1 - maxLength;
}
|
|||
|
|
|||
|