Voici le problème (6.7 ch6 ) du livre Algorithms (de Vazirani) qui diffère légèrement du problème classique qui consiste à trouver le plus long palindrome . Comment puis-je résoudre ce problème ?
Une sous-séquence est palindromique si elle est le même si lu gauche à droite ou de droite à gauche. Par exemple, le séquence
A,C,G,T,G,T,C,A,A,A,A,T,C,G
a de nombreuses sous-séquences palindromiques, y compris
A,C,G,C,A
etA,A,A,A
(par contre, la sous-séquenceA,C,T
n'est pas palindromique). Concevoir un algorithme qui prend une séquencex[1 ...n]
et retourne le (longueur du) plus longue sous-séquence palindromique. Ses le temps en cours devrait êtreO(n^2)
Ceci peut être résolu en O (n ^ 2) en utilisant une programmation dynamique. Fondamentalement, le problème est de construire la plus longue sous-séquence palindromique dans x[i...j]
en utilisant la plus longue sous-séquence pour x[i+1...j]
, x[i,...j-1]
et x[i+1,...,j-1]
(si la première et la dernière lettre sont identiques).
Premièrement, la chaîne vide et une chaîne de caractères unique sont trivialement un palindrome . Notez que pour une sous-chaîne x[i,...,j]
, si x[i]==x[j]
, nous pouvons dire que la longueur du plus long palindrome est le plus long palindrome sur x[i+1,...,j-1]+2
. S'ils ne correspondent pas, le plus long palindrome est le maximum de celui de x[i+1,...,j]
et de y[i,...,j-1]
.
Cela nous donne la fonction:
longest(i,j)= j-i+1 if j-i<=0,
2+longest(i+1,j-1) if x[i]==x[j]
max(longest(i+1,j),longest(i,j-1)) otherwise
Vous pouvez simplement implémenter une version mémoisée de cette fonction ou coder un tableau de la plus longue [i] [j] ascendante.
Cela ne vous donne que la longueur de la sous-séquence la plus longue, pas la sous-séquence elle-même. Mais il peut facilement être étendu pour le faire aussi.
Ce problème peut également être résolu en tant que variante d’un problème très courant appelé problème LCS (Longest Common Sub Sequence). Soit la chaîne en entrée représentée par un tableau de caractères s1 [0 ... n-1].
1) Inverser la séquence donnée et stocker l’inverse dans un autre tableau, par exemple s2 [0..n-1], qui est essentiellement s1 [n-1 .... 0]
2) Le LCS de la séquence donnée s1 et de la séquence inverse s2 sera la plus longue séquence palindromique.
Cette solution est également une solution O (n ^ 2).
Cela me laisse un peu perplexe de faire la différence entre sous-chaîne et sous-séquence (voir Ex. 6.8 et 6.11). ne suis pas tout à fait sûr de l'initialisation> <
for i = 1 to n do
for j = 1 to i-1 do
L(i,j) = 0
for i = 1 to n do
L(i,i) = 1
for i = n-1 to 1 do //pay attention to the order when filling the table
for j = i+1 to n do
if x[i] = x[j] then
L(i,j) = 2 + L(i+1, j-1)
else do
L(i,j) = max{L(i+1, j), L(i, j-1)}
return max L(i,j)
se préparer pour l'algorithme final ...
importer Java.util.HashSet;
importer Java.util.Scanner;
/** * @param args * On nous donne une chaîne et nous devons trouver la sous-séquence la plus longue de cette chaîne, palindrome * Dans ce code, nous avons utilisé hashset afin de déterminer le jeu unique de sous-chaînes dans les chaînes données * /
classe publique NumberOfPalindrome {
/**
* @param args
* Given a string find the longest possible substring which is a palindrome.
*/
public static HashSet<String> h = new HashSet<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
for(int i=0;i<=s.length()/2;i++)
h.add(s.charAt(i)+"");
longestPalindrome(s.substring(0, (s.length()/2)+(s.length()%2)));
System.out.println(h.size()+s.length()/2);
System.out.print(h);
}
public static void longestPalindrome(String s){
//System.out.println(s);
if(s.length()==0 || s.length()==1)
return;
if(checkPalindrome(s)){
h.add(s);
}
longestPalindrome(s.substring(0, s.length()-1));
longestPalindrome(s.substring(1, s.length()));
}
public static boolean checkPalindrome(String s){
//System.out.println(s);
int i=0;int j=s.length()-1;
while(i<=j){
if(s.charAt(i)!=s.charAt(j))
return false;
i++;j--;
}
return true;
}
}
Implémentation Java de la plus longue séquence palindrome
public class LongestPalindrome
{
int max(int x , int y)
{
return (x>y)? x:y;
}
int lps(char[] a ,int i , int j)
{
if(i==j) //If only 1 letter
{
return 1;
}
if(a[i] == a[j] && (i+1) == j) // if there are 2 character and both are equal
{
return 2;
}
if(a[i] == a[j]) // If first and last char are equal
{
return lps(a , i+1 , j-1) +2;
}
return max(lps(a,i+1 ,j),lps(a,i,j-1));
}
public static void main(String[] args)
{
String s = "NAMAN IS NAMAN";
LongestPalindrome p = new LongestPalindrome();
char[] c = s.toCharArray();
System.out.print("Length of longest seq is" + p.lps(c,0,c.length-1));
}
}
private static int findLongestPalindromicSubsequence(String string) {
int stringLength = string.length();
int[][] l = new int[stringLength][stringLength];
for(int length = 1; length<= stringLength; length++){
for(int left = 0;left<= stringLength - length;left++){
int right = left+ length -1;
if(length == 1){
l[left][right] = 1;
}
else{
if(string.charAt(left) == string.charAt(right)){
//L(0, n-1) = L(1, n-2) + 2
if(length == 2){
// aa
l[left][right] = 2;
}
else{
l[left][right] = l[left+1][right-1]+2;
}
}
else{
//L(0, n-1) = MAX ( L(1, n-1) , L(0, n-2) )
l[left][right] = (l[left+1][right] > l[left][right-1])?l[left+1][right] : l[left][right-1];
}
}
}
}
return l[0][stringLength-1];
}