Palíndromo dividido
Descrição do título
Dada uma string, retorna o número mínimo de cortes que cortam todas as str em strings de palíndromo.
Insira uma descrição:
A entrada contém uma linha de string, representando str (1 ≤ lengthstr ≤ 5000) str (1 \ leq length_ {str} \ leq 5000)s t r ( 1≤l e n g t hs t r≤5 0 0 0 )。
Descrição de saída:
Produza um inteiro, representando o número mínimo de cortes para cortar todas as str em strings de palíndromo.
Exemplo 1
entrar
ABA
Resultado
0
Descrição
本身是回文串,不需要切割,直接输出0
Exemplo 2
entrar
ABCBAEEE
Resultado
1
Descrição
切割1次,变为“ABCBA”和“EEE”
Observações:
Complexidade de tempo O (n 2) O (n ^ 2)O ( n2 ), complexidade de espaço adicionalO (n 2) O (n ^ 2)O ( n2 )。
responda:
Programaçao dinamica. Deixe F [i] denotar que str [0 ... i] precisa ser dividido pelo menos várias vezes antes que todo str [0 ... i] possa ser dividido em strings de palíndromo. Calcule F [i] da esquerda para a direita, o processo é o seguinte:
- Suponha que a posição atual seja j (j <= i <len), se str [j ... i] for um palíndromo, então F [i] = F [j-1] +1, o que significa em str [0 ... i] Na substring, str [j ... i] já é uma string de palíndromo, é usada como uma parte separada, e o resto usa seu número mínimo de divisões de palíndromo, a saber F [j-1];
- Deixe j enumerar de 0 a i, encontre o valor mínimo em todos os casos, ou seja, F [i] = min {F [j-1] +1 (0 <= j <= i <len, e str [ j ... i] é um palíndromo)};
- Para determinar rapidamente se str [j ... i] é um palíndromo, o processo é o seguinte:
- Defina uma matriz bidimensional p, p [j] [i] = truep [j] [i] = truep [ j ] [ i ]=t r u e significa str [j ... i] é um palíndromo;
- 若p [j] [i] = verdadeirop [j] [i] = verdadeirop [ j ] [ i ]=t r u e deve ser os seguintes três casos:
- str [j ... i] tem apenas um caractere;
- str [j… i] tem dois caracteres e os dois caracteres são iguais;
- str [j + 1 ... i-1] é uma string palíndromo, ou seja, p [j + 1] [i - 1] = verdadeiro p [j + 1] [i-1] = verdadeirop [ j+1 ] [ i-1 ]=t r u e, 且 str [j] == str [i] ;
- i vai da esquerda para a direita, j vai da direita para a esquerda, então p [j + 1] [i - 1] p [j + 1] [i-1]p [ j+1 ] [ i-1 ] Deve ter sido calculado.
Código:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5005;
char s[N];
bool p[N][N];
int f[N];
int main(void) {
scanf("%s", s);
int n = strlen(s);
for ( int i = 1; i < n; ++i ) {
f[i] = i;
for ( int j = i; j >= 0; --j ) {
if ( s[i] == s[j] && ( i-j<2 || p[j+1][i-1] ) ) {
p[j][i] = true;
if (!j) f[i] = 0;
else f[i] = min(f[i], f[j - 1] + 1);
}
}
}
printf("%d\n", f[n - 1]);
return 0;
}