Минимальное количество символов, вставляемых в конец строки, чтобы сделать ее палиндромом
вопрос такой--
мы должны найти минимальное количество символов для вставки В конце строки, чтобы сделать его палиндромом.
Итак, в моих усилиях сделать эту проблему, я решил, что это эквивалентно поиску самой большой палиндромной подстроки, которая также является суффиксом строки.
Я мог бы сделать это в O(n^2) легко, но я ищу решение O(n), которое, вероятно, возможно, используя модифицированный KMP. Кто-нибудь, пожалуйста, помогите мне разобраться.
2 ответов
у меня есть подход, который использует хэширование, размещенное в качестве ответа здесь.
вы действительно можете использовать KMP. Вы можете вычислить функции префикса для обратной строки, а затем повторите начальную строку слева направо:
KMP вычисляет функцию prefix[i] = longest prefix of the string that is a suffix of string[1..i]
однако, мы хотим знать the longest suffix of our string that is a prefix of the reversed string
. Почему? Если у нас есть:
15232 => reverse = 23251
тогда самый длинный суффикс строки, которая является префиксом обратной строки 232
. Это палиндром, и он позволяет нам найти то, что вы просите, потому что суффикс строки перекрывает префикс обратной строки, если эти два палиндрома.
у вас есть дела:
prefix[i] = length - i => you can get a palindrome of
length 2*prefix[i] centered at i and i+1
prefix[i] = length - i + 1 => you can get a palindrome of
length 2*prefix[i] - 1 centered at i
prefix[i] < length - i => you can't have a palindrome, ignore this position
поэтому достаточно вычислить префиксную функцию алгоритма KMP.
простой код, чтобы вставить минимальное количество символов и вернуть их, чтобы сделать данную строку pallindrome
#include <bits/stdc++.h>
using namespace std;
bool isPalin(char *s,int x,int l)
{
for(int i=x,j=l-1;i<j;i++,j--)
if(s[i]!=s[j])
return 0;
return 1;
}
char * f(char *s)
{
// if s is NULL return NULL
if(!s)
return NULL;
int i,l,j;
l=strlen(s);
for(i=0;i<l;i++)
{
// check if string is pallindrome from [i...l-1]
if(isPalin(s,i,l) == 1)
break;
}
// if s is already a pallindrome return NULL
if(i==0)
return NULL;
int k=0;
// make a char*
char *ans = new char[i+1];
for(i-=1;i>=0;i--)
ans[k++]=s[i];
ans[k++]='';
return ans;
}
int main() {
char *a = "wxytabbat";
cout<<f(a)<<"\n";
return 0;
}