У этой задачи есть как минимум два возможных решения.
Первое решение является более простым с "идейной"
точки зрения. Оно заключается в двоичном поиске искомой длины префикса.
Если для проверки префикса использовать КМП-поиск, то алгоритм будет
иметь сложность O(n*log(n)). Второе решение короче и имеет сложность
O(n), но требует более глубокого знания метода КМП. На самом деле в код,
приведенный во втором выпуске рассылки, достаточно внести минимальные
изменения. Искомая длина префикса будет равна максимуму по значениям
переменной k после каждой итерации второго цикла. Вот и все!
Ниже приведен текст программы. Код КМП-поиска
немного отличается от приведенного ранее, потому что здесь используется
индексация массивов с 0.
#include <stdio.h>
#include <stdlib.h>
const int max = 30001; // максимальная длина строки
void main()
{
char a[max], b[max];
int c[max];
int i, j, k, m, t;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%s %s", a, b); // вводим данные
// первая часть КМП-поиска, заполняем массив c
c[0] = k = 0;
for (i = 1; a[i]; i++)
{
while (k && a[i] != a[k]) k = c[k-1];
if (a[i] == a[k]) k++;
c[i] = k;
}
t = i; // запомним длину первой строки
m = 0; // в переменной m будет храниться максимальная длина префикса
// вторая часть КМП-поиска
k = 0;
for (i = 0; b[i]; i++)
{
while (k && b[i] != a[k]) k = c[k-1];
if (b[i] == a[k]) k++;
if (k > m) m = k; // берем максимум по значениям k
if (k == t) break; // длина префикса не может быть больше длины строки
}
printf("%d\n", m); // вывод ответа
exit(0);
}
Результаты по задаче №3 "Префикс-подстрока" (5 баллов).
Ник
Результат
arti
wrong answer on test #3
bolt
wrong answer on test #1
DEathkNIghtS
accepted
Решение задачи №4 "Палиндром" (8 баллов).
Задача очень простая. Палиндромы делятся на два вида:
четной длины и нечетной длины. Мы перебираем позицию для центра подпалиндрома.
И для каждой позиции находим максимальный подпалиндром нечетной и четной
длины. Сложность алгоритма получается O(n2), что приемлемо при
ограничении n <= 2000.
Текст программы:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max(a,b) (((a)>(b))?(a):(b))
const int max=2001;
int f(int n, char a[], int i, int j)
{
while (0 <= i - 1 && j + 1 < n && a[i - 1] == a[j + 1]) i--, j++;
return (j - i + 1);
}
void main()
{
int n, i, p, m;
char a[max];
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%s", a); // вводим данные
n = strlen(a);
m = 0;
for (i = 0; i < n; i++) // перебираем центр
{
p = f(n, a, i, i); // нечетный палиндром
m = max(m, p);
if (i + 1 < n && a[i + 1] == a[i])
{
p = f(n, a, i, i + 1); // четный палиндром
m = max(m, p);
}
}
printf("%d\n", m); // выводим результат
exit(0);
}
Результаты по задаче №4 "Палиндром" (8 баллов).
Ник
Результат
arti
accepted
bolt
wrong answer on test #5
DEathkNIghtS
accepted
Условия задач, тесты и решения вы всегда можете
найти на сайте accepted.narod.ru.
Ведущий рассылкой: Виктор Журавлев
Вопросы, пожелания, предложения пишите на мой
e-mail.