how to find longest palindromic subsequence? - algorithm

Here is the problem (6.7 ch6 ) from Algorithms book (by Vazirani) that slightly differs from the classical problem that finding longest palindrome. How can I solve this problem ?
A subsequence is palindromic if it is
the same whether read left to right or
right to left. For instance, the
sequence
A,C,G,T,G,T,C,A,A,A,A,T,C,G
has many palindromic subsequences,
including A,C,G,C,A and A,A,A,A
(on the other hand, the subsequence
A,C,T is not palindromic). Devise an
algorithm that takes a sequence x[1
...n] and returns the (length of the)
longest palindromic subsequence. Its
running time should be O(n^2)

This can be solved in O(n^2) using dynamic programming. Basically, the problem is about building the longest palindromic subsequence in x[i...j] using the longest subsequence for x[i+1...j], x[i,...j-1] and x[i+1,...,j-1] (if first and last letters are the same).
Firstly, the empty string and a single character string is trivially a palindrome.
Notice that for a substring x[i,...,j], if x[i]==x[j], we can say that the length of the longest palindrome is the longest palindrome over x[i+1,...,j-1]+2. If they don't match, the longest palindrome is the maximum of that of x[i+1,...,j] and y[i,...,j-1].
This gives us the function:
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
You can simply implement a memoized version of that function, or code a table of longest[i][j] bottom up.
This gives you only the length of the longest subsequence, not the actual subsequence itself. But it can easily be extended to do that as well.

This problem can also be done as a variation of a very common problem called the LCS(Longest Common sub sequence) problem.
Let the input string be represented by a character array s1[0...n-1].
1) Reverse the given sequence and store the reverse in another array say s2[0..n-1] which in essence is s1[n-1....0]
2) LCS of the given sequence s1 and reverse sequence s2 will be the longest palindromic sequence.
This solution is also a O(n^2) solution.

It makes me a little confused that the difference between substring and subsequence.(See Ex6.8 and 6.11) According to our comprehension of subsequence, the giving example doesn't have the palindromic subsequence ACGCA.
Here's my pseudo code, I'm not quite sure about the initialization ><
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)
preparing for the algorithm final...

Working Java Implementation of Longest Palindrome Sequence
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));
}
}

import java.util.HashSet;
import java.util.Scanner;
/**
* #param args
* We are given a string and we need to find the longest subsequence in that string which is palindrome
* In this code we have used hashset in order to determine the unique set of substring in the given strings
*/
public class 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;
}
}

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];
}

Program to find the longest palindrome substring from a given string.
package source;
import java.util.ArrayList;
public class LongestPalindrome
{
//Check the given string is palindrome by
public static boolean isPalindrome (String s)
{
StringBuffer sb = new StringBuffer(s);
if(s.equalsIgnoreCase(sb.reverse().toString()))
return true;
else
return false;
}
public static void main(String[] args)
{
//String / word without space
String str = "MOMABCMOMOM"; // "mom" //"abccbabcd"
if(str.length() > 2 )
{
StringBuffer sb = new StringBuffer();
ArrayList<String> allPalindromeList = new ArrayList<>();
for(int i=0; i<str.length(); i++)
{
for(int j=i; j<str.length(); j++)
{
sb.append(str.charAt(j));
if( isPalindrome(sb.toString()) ) {
allPalindromeList.add(sb.toString());
}
}
//clear the stringBuffer
sb.delete(0, sb.length());
}
int maxSubStrLength = -1;
int indexMaxSubStr = -1;
int index = -1;
for (String subStr : allPalindromeList) {
++index;
if(maxSubStrLength < subStr.length()) {
maxSubStrLength = subStr.length();
indexMaxSubStr = index;
}
}
if(maxSubStrLength > 2)
System.out.println("Maximum Length Palindrome SubString is : "+allPalindromeList.get(indexMaxSubStr));
else
System.out.println("Not able to find a Palindrome who is three character in length!!");
}
}
}

for each letter in the string:
set the letter as the middle of the palindrome (current Length = 1)
check how long would be the palindrome if this is its middle
if this palindrome is longer than the one we found (until now) : keep the index and the size of the palindrome.
O(N^2) : since we have one loop that choose the middle and one loop that check how long the palindrome if this is the middle. each loop runs from 0 to O(N) [the first one from 0 to N-1 and the second one is from 0 to (N-1)/2]
for example:
D B A B C B A
i=0 : D is the middle of the palindrome, can't be longer than 1 (since it's the first one)
i=1: B is the middle of the palindrome, check char before and after B : not identical (D in one side and A in the other) --> length is 1.
i=2 : A is middle of the palindrome, check char before and after A : both B --> length is 3. check chars with gap of 2: not identiacl (D in one side and C in the other) --> length is 3.
etc.

Input : A1,A2,....,An
Goal : Find the longest strictly increasing subsequence (not necessarily contiguous)​.
L(j): Longest strictly increasing subsequence ending at j
L(j): max{ L(i)}+1 } where i < j and A[i] < A[j]
Then find max{ L(j) } for all j
You will get the source code here

Related

How to print the Longest Palindromic Subsequence? If there are multiple LPS we need to print the one which starts at lowest index

Here is my code, it prints the LPS correctly but can't print the one which starts from the lowest index if multiple LPS exist. I tried handling a case seperately when dp[i][j-1]==dp[i-1][j] but for some reason that dosen't work also. Any help would really be appreciated.
public class Solution {
public static String longestPalinSubstring(String str) {
String rev = reverse(str);
int n = str.length();
int[][] dp = new int[n+1][n+1];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(str.charAt(i-1)==rev.charAt(j-1)){
dp[i][j] = 1 + dp[i-1][j-1];
}else{
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
int i=n, j=n;
String ans="";
while(i>0 && j>0){
if(str.charAt(i-1)==rev.charAt(j-1)){
ans+=str.charAt(i-1);
--i;
--j;
}else{
if(dp[i-1][j]<dp[i][j-1]){
j--;
}else{
i--;
}
}
}
return reverse(ans);
}
public static String reverse(String s){
String ans = "";
for(int i=s.length()-1;i>=0;i--){
ans += s.charAt(i);
}
return ans;
}
}
I am providing an alternative yet easy dynamic programming implementation which will solve your problem.
dp[i][j] = 1 represents palindrome of size i ending at position j in the given string.
Example: str = "aprabaprrbcb" then dp[3][5] represents "aba". Since "aba" is palindrome, dp[3][5] = 1.
We just need to check if first and last character of the current sub-string is equal. If equal then check if inner sub-string (string after removing first and last character of current string) is palindrome or not. Since the inner sub-string size will be i-2 and ends at j-1, hence we check dp[i-2][j-1].
Now maintain 2 variables lar_size and lar_pos for size of longest palindrome and last index of that palindrome.
import java.util.Scanner;
public class LPS {
public static void main(String[] args){
Scanner sc= new Scanner(System.in);
String str = sc.nextLine();
sc.close();
int n= str.length();
int[][] dp = new int[n+1][n+1];
int lar_size=-1;
int lar_pos= -1;
for(int i=0;i<=n;i++){
dp[0][i]=1; //string of length 0 ending at position i is a palindrome
dp[1][i]=1; //string of length 1 ending at position i is a palindrome
}
//
for( int i=2;i<=n;i++){
for( int j=i; j<=n;j++){
if(str.charAt(j-1) == str.charAt(j-i)){
if(dp[i-2][j-1] == 1){
dp[i][j]=1;
if(lar_size < i){ // for lowest index palindrome
lar_size=i;
lar_pos=j;
}
}
}
}
}
System.out.println(lar_size+" "+(lar_pos-lar_size+1));
String ans="";
for(int i=0;i<lar_size;i++){
ans+=str.charAt(lar_pos-lar_size+1 +i);
}
System.out.println(ans);
}
}

Print all palindromes of size greater than equal to 3 of a given string [duplicate]

If the input is 'abba' then the possible palindromes are a, b, b, a, bb, abba.
I understand that determining if string is palindrome is easy. It would be like:
public static boolean isPalindrome(String str) {
int len = str.length();
for(int i=0; i<len/2; i++) {
if(str.charAt(i)!=str.charAt(len-i-1) {
return false;
}
return true;
}
But what is the efficient way of finding palindrome substrings?
This can be done in O(n), using Manacher's algorithm.
The main idea is a combination of dynamic programming and (as others have said already) computing maximum length of palindrome with center in a given letter.
What we really want to calculate is radius of the longest palindrome, not the length.
The radius is simply length/2 or (length - 1)/2 (for odd-length palindromes).
After computing palindrome radius pr at given position i we use already computed radiuses to find palindromes in range [i - pr ; i]. This lets us (because palindromes are, well, palindromes) skip further computation of radiuses for range [i ; i + pr].
While we search in range [i - pr ; i], there are four basic cases for each position i - k (where k is in 1,2,... pr):
no palindrome (radius = 0) at i - k
(this means radius = 0 at i + k, too)
inner palindrome, which means it fits in range
(this means radius at i + k is the same as at i - k)
outer palindrome, which means it doesn't fit in range
(this means radius at i + k is cut down to fit in range, i.e because i + k + radius > i + pr we reduce radius to pr - k)
sticky palindrome, which means i + k + radius = i + pr
(in that case we need to search for potentially bigger radius at i + k)
Full, detailed explanation would be rather long. What about some code samples? :)
I've found C++ implementation of this algorithm by Polish teacher, mgr Jerzy Wałaszek.
I've translated comments to english, added some other comments and simplified it a bit to be easier to catch the main part.
Take a look here.
Note: in case of problems understanding why this is O(n), try to look this way:
after finding radius (let's call it r) at some position, we need to iterate over r elements back, but as a result we can skip computation for r elements forward. Therefore, total number of iterated elements stays the same.
Perhaps you could iterate across potential middle character (odd length palindromes) and middle points between characters (even length palindromes) and extend each until you cannot get any further (next left and right characters don't match).
That would save a lot of computation when there are no many palidromes in the string. In such case the cost would be O(n) for sparse palidrome strings.
For palindrome dense inputs it would be O(n^2) as each position cannot be extended more than the length of the array / 2. Obviously this is even less towards the ends of the array.
public Set<String> palindromes(final String input) {
final Set<String> result = new HashSet<>();
for (int i = 0; i < input.length(); i++) {
// expanding even length palindromes:
expandPalindromes(result,input,i,i+1);
// expanding odd length palindromes:
expandPalindromes(result,input,i,i);
}
return result;
}
public void expandPalindromes(final Set<String> result, final String s, int i, int j) {
while (i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)) {
result.add(s.substring(i,j+1));
i--; j++;
}
}
So, each distinct letter is already a palindrome - so you already have N + 1 palindromes, where N is the number of distinct letters (plus empty string). You can do that in single run - O(N).
Now, for non-trivial palindromes, you can test each point of your string to be a center of potential palindrome - grow in both directions - something that Valentin Ruano suggested.
This solution will take O(N^2) since each test is O(N) and number of possible "centers" is also O(N) - the center is either a letter or space between two letters, again as in Valentin's solution.
Note, there is also O(N) solution to your problem, based on Manacher's algoritm (article describes "longest palindrome", but algorithm could be used to count all of them)
I just came up with my own logic which helps to solve this problem.
Happy coding.. :-)
System.out.println("Finding all palindromes in a given string : ");
subPal("abcacbbbca");
private static void subPal(String str) {
String s1 = "";
int N = str.length(), count = 0;
Set<String> palindromeArray = new HashSet<String>();
System.out.println("Given string : " + str);
System.out.println("******** Ignoring single character as substring palindrome");
for (int i = 2; i <= N; i++) {
for (int j = 0; j <= N; j++) {
int k = i + j - 1;
if (k >= N)
continue;
s1 = str.substring(j, i + j);
if (s1.equals(new StringBuilder(s1).reverse().toString())) {
palindromeArray.add(s1);
}
}
}
System.out.println(palindromeArray);
for (String s : palindromeArray)
System.out.println(s + " - is a palindrome string.");
System.out.println("The no.of substring that are palindrome : "
+ palindromeArray.size());
}
Output:-
Finding all palindromes in a given string :
Given string : abcacbbbca
******** Ignoring single character as substring palindrome ********
[cac, acbbbca, cbbbc, bb, bcacb, bbb]
cac - is a palindrome string.
acbbbca - is a palindrome string.
cbbbc - is a palindrome string.
bb - is a palindrome string.
bcacb - is a palindrome string.
bbb - is a palindrome string.
The no.of substring that are palindrome : 6
I suggest building up from a base case and expanding until you have all of the palindomes.
There are two types of palindromes: even numbered and odd-numbered. I haven't figured out how to handle both in the same way so I'll break it up.
1) Add all single letters
2) With this list you have all of the starting points for your palindromes. Run each both of these for each index in the string (or 1 -> length-1 because you need at least 2 length):
findAllEvenFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i) != str.charAt(index+i+1))
return; // Here we found out that this index isn't a center for palindromes of >=i size, so we can give up
outputList.add(str.substring(index-i, index+i+1));
i++;
}
}
//Odd looks about the same, but with a change in the bounds.
findAllOddFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i-1) != str.charAt(index+i+1))
return;
outputList.add(str.substring(index-i-1, index+i+1));
i++;
}
}
I'm not sure if this helps the Big-O for your runtime, but it should be much more efficient than trying each substring. Worst case would be a string of all the same letter which may be worse than the "find every substring" plan, but with most inputs it will cut out most substrings because you can stop looking at one once you realize it's not the center of a palindrome.
I tried the following code and its working well for the cases
Also it handles individual characters too
Few of the cases which passed:
abaaa --> [aba, aaa, b, a, aa]
geek --> [g, e, ee, k]
abbaca --> [b, c, a, abba, bb, aca]
abaaba -->[aba, b, abaaba, a, baab, aa]
abababa -->[aba, babab, b, a, ababa, abababa, bab]
forgeeksskeegfor --> [f, g, e, ee, s, r, eksske, geeksskeeg,
o, eeksskee, ss, k, kssk]
Code
static Set<String> set = new HashSet<String>();
static String DIV = "|";
public static void main(String[] args) {
String str = "abababa";
String ext = getExtendedString(str);
// will check for even length palindromes
for(int i=2; i<ext.length()-1; i+=2) {
addPalindromes(i, 1, ext);
}
// will check for odd length palindromes including individual characters
for(int i=1; i<=ext.length()-2; i+=2) {
addPalindromes(i, 0, ext);
}
System.out.println(set);
}
/*
* Generates extended string, with dividors applied
* eg: input = abca
* output = |a|b|c|a|
*/
static String getExtendedString(String str) {
StringBuilder builder = new StringBuilder();
builder.append(DIV);
for(int i=0; i< str.length(); i++) {
builder.append(str.charAt(i));
builder.append(DIV);
}
String ext = builder.toString();
return ext;
}
/*
* Recursive matcher
* If match is found for palindrome ie char[mid-offset] = char[mid+ offset]
* Calculate further with offset+=2
*
*
*/
static void addPalindromes(int mid, int offset, String ext) {
// boundary checks
if(mid - offset <0 || mid + offset > ext.length()-1) {
return;
}
if (ext.charAt(mid-offset) == ext.charAt(mid+offset)) {
set.add(ext.substring(mid-offset, mid+offset+1).replace(DIV, ""));
addPalindromes(mid, offset+2, ext);
}
}
Hope its fine
public class PolindromeMyLogic {
static int polindromeCount = 0;
private static HashMap<Character, List<Integer>> findCharAndOccurance(
char[] charArray) {
HashMap<Character, List<Integer>> map = new HashMap<Character, List<Integer>>();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (map.containsKey(c)) {
List list = map.get(c);
list.add(i);
} else {
List list = new ArrayList<Integer>();
list.add(i);
map.put(c, list);
}
}
return map;
}
private static void countPolindromeByPositions(char[] charArray,
HashMap<Character, List<Integer>> map) {
map.forEach((character, list) -> {
int n = list.size();
if (n > 1) {
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (list.get(i) + 1 == list.get(j)
|| list.get(i) + 2 == list.get(j)) {
polindromeCount++;
} else {
char[] temp = new char[(list.get(j) - list.get(i))
+ 1];
int jj = 0;
for (int ii = list.get(i); ii <= list
.get(j); ii++) {
temp[jj] = charArray[ii];
jj++;
}
if (isPolindrome(temp))
polindromeCount++;
}
}
}
}
});
}
private static boolean isPolindrome(char[] charArray) {
int n = charArray.length;
char[] temp = new char[n];
int j = 0;
for (int i = (n - 1); i >= 0; i--) {
temp[j] = charArray[i];
j++;
}
if (Arrays.equals(charArray, temp))
return true;
else
return false;
}
public static void main(String[] args) {
String str = "MADAM";
char[] charArray = str.toCharArray();
countPolindromeByPositions(charArray, findCharAndOccurance(charArray));
System.out.println(polindromeCount);
}
}
Try out this. Its my own solution.
// Maintain an Set of palindromes so that we get distinct elements at the end
// Add each char to set. Also treat that char as middle point and traverse through string to check equality of left and right char
static int palindrome(String str) {
Set<String> distinctPln = new HashSet<String>();
for (int i=0; i<str.length();i++) {
distinctPln.add(String.valueOf(str.charAt(i)));
for (int j=i-1, k=i+1; j>=0 && k<str.length(); j--, k++) {
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(j)))) {
distinctPln.add(str.substring(j,i+1));
}
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(i,k+1));
}
if ( (new Character(str.charAt(j))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(j,k+1));
} else {
continue;
}
}
}
Iterator<String> distinctPlnItr = distinctPln.iterator();
while ( distinctPlnItr.hasNext()) {
System.out.print(distinctPlnItr.next()+ ",");
}
return distinctPln.size();
}
Code is to find all distinct substrings which are palindrome.
Here is the code I tried. It is working fine.
import java.util.HashSet;
import java.util.Set;
public class SubstringPalindrome {
public static void main(String[] args) {
String s = "abba";
checkPalindrome(s);
}
public static int checkPalindrome(String s) {
int L = s.length();
int counter =0;
long startTime = System.currentTimeMillis();
Set<String> hs = new HashSet<String>();
// add elements to the hash set
System.out.println("Possible substrings: ");
for (int i = 0; i < L; ++i) {
for (int j = 0; j < (L - i); ++j) {
String subs = s.substring(j, i + j + 1);
counter++;
System.out.println(subs);
if(isPalindrome(subs))
hs.add(subs);
}
}
System.out.println("Total possible substrings are "+counter);
System.out.println("Total palindromic substrings are "+hs.size());
System.out.println("Possible palindromic substrings: "+hs.toString());
long endTime = System.currentTimeMillis();
System.out.println("It took " + (endTime - startTime) + " milliseconds");
return hs.size();
}
public static boolean isPalindrome(String s) {
if(s.length() == 0 || s.length() ==1)
return true;
if(s.charAt(0) == s.charAt(s.length()-1))
return isPalindrome(s.substring(1, s.length()-1));
return false;
}
}
OUTPUT:
Possible substrings:
a
b
b
a
ab
bb
ba
abb
bba
abba
Total possible substrings are 10
Total palindromic substrings are 4
Possible palindromic substrings: [bb, a, b, abba]
It took 1 milliseconds

How can I find most frequent combinations of numbers in a list?

Imagine you have a list of numbers (or letters), such as
1177783777297461145777267337774652113777236237118777
I want to find the most frequent combinations of numbers in this list:
for 1-digit-long combinations - it is the most frequent number in this list
for 2-digit-long combinations - probably '11'
for 3-digits-long combinations - probably '777' etc
Is there some special algorythm for such a tasks?
UPDATE
Well, by myself I have coded the following (Java). Looks like execution time is proportional to data size multiplied by pattern size:
public static void main(String[] args)
{
int DATA_SIZE = 10000;
int[] data = new int[DATA_SIZE];
for (int i = 0; i < DATA_SIZE; i++)
{
data[i] = (int) (10 * Math.random()) % 10;
System.out.print(data[i]);
}
int[] pattern1 = new int[]{1, 2, 3};
int[] pattern2 = new int[]{7, 7, 7};
int[] pattern3 = new int[]{7, 7};
System.out.println();
System.out.println(match(data, pattern1));
System.out.println(match(data, pattern2));
System.out.println(match(data, pattern3));
}
static int match(int[] data, int[] pattern)
{
int matches = 0;
int i = 0;
while (i < data.length)
{
matches = isEqual(data, i, pattern) ? matches + 1 : matches;
i++;
}
return matches;
}
static boolean isEqual(int[] a, int startIndex, int[] a2)
{
if (a == a2)
{
return true;
}
if (a == null || a2 == null)
{
return false;
}
for (int i = 0; i < a2.length; i++)
{
if (a[startIndex + i] != a2[i])
{
return false;
}
}
return true;
}
This can be done in quadratic time, though I'm curious about faster approaches. The idea is iterating over the possible length values k=1..N, and on each iteration loop through the string to find the most frequent sequence of length k.
The inner loop can use a hashtable for counting the frequencies efficiently.
To find the largest number of repeats of a sequence of length at least k in a string of length n, you can build a suffix tree (http://en.wikipedia.org/wiki/Suffix_tree) in linear time, then find the node that has the most children that describes sequences of length k (or more) from the root.
Overall, this is linear time in the length of the input string.
For small k, you're better off with a naive algorithm:
from collections import Counter
def input(s, k):
c = Counter()
for i in xrange(len(s) - k):
c[s[i : i + k]] += 1
return c.most_common(1)[0][0]
for k in xrange(1, 4):
print input('1177783777297461145777267337774652113777236237118777', k)
Simply go through array mantaining the variable with most frequent combination already found and auxillary hash table where keys are searching patterns and values are number of occurences in your input data. When you find next pattern, increment the value in hash table and if necessary the value of current most frequent combination.
REGEX - thats the solution to your problem with great efficiency
http://www.vogella.com/articles/JavaRegularExpressions/article.html
check this it will help you . If you still cant get through lemme know ,ill help

How to find the longest palindromic subsequence (not its length)

I want to find out the longest palindromic subsequence in a string. Everywhere I find the algorithm to find out the length of the subsequence, with the statement that the algo can be extended to return the subsequence as well, but nowhere have I found how. Can anybody explain how can I get the sequence as well?
Since you mentioned the link Longest Palindromic Subsequence in geeksforgeeks, I modified the solution to output the result. I think we need one auxiliary two-dimensions array to stored how the palindromic subsequence comes from, so we can get the result through the auxiliary array at last. You can see the logic in the below code:
#include<iostream>
#include<cstring>
using namespace std;
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
// Returns the length of the longest palindromic subsequence in seq
int lps(char *str,char *result)
{
int n = strlen(str);
int i, j, cl;
int L[n][n]; // Create a table to store results of subproblems
int Way[n][n];// Store how the palindrome come from.
// Strings of length 1 are palindrome of lentgh 1
for (i = 0; i < n; i++)
{
L[i][i] = 1;
Way[i][i]=0;
}
// Build the table. Note that the lower diagonal values of table are
// useless and not filled in the process. The values are filled in a
// manner similar to Matrix Chain Multiplication DP solution (See
// http://www.geeksforgeeks.org/archives/15553). cl is length of
// substring
for (cl=2; cl<=n; cl++)
{
for (i=0; i<n-cl+1; i++)
{
j = i+cl-1;
if (str[i] == str[j] && cl == 2)
{
L[i][j] = 2;
Way[i][j]=0;
}
else if (str[i] == str[j])
{
L[i][j] = L[i+1][j-1] + 2;
Way[i][j]=0;
}
else
{
if(L[i][j-1]>L[i+1][j])
{
L[i][j]=L[i][j-1];
Way[i][j]=1;
}
else
{
L[i][j]=L[i+1][j];
Way[i][j]=2;
}
}
}
}
int index=0;
int s=0,e=n-1;
while(s<=e)
{
if(Way[s][e]==0)
{
result[index++]=str[s];
s+=1;
e-=1;
}
else if(Way[s][e]==1)e-=1;
else if(Way[s][e]==2)s+=1;
}
int endIndex=(L[0][n-1]%2)?index-1:index;
for(int k=0;k<endIndex;++k)result[L[0][n-1]-1-k]=result[k];
result[index+endIndex]='\0';
return L[0][n-1];
}
/* Driver program to test above functions */
int main()
{
char seq[] = "GEEKSFORGEEKS";
char result[20];
cout<<"The lnegth of the LPS is "<<lps(seq,result)<<":"<<endl;
cout<<result<<endl;
getchar();
return 0;
}
Hope it helps!
Below is the explanation:
Let X[0..n-1] be the input sequence of length n and L(0, n-1) be the length of the longest palindromic sub-sequence of X[0..n-1].
There are 5 cases in total.
1)Every single character is a palindrome of length 1.
L(i, i) = 1 for all indexes i in given sequence.
2)There are only 2 characters and both are same.
L(i, j) = 2.
3)There are more than two characters, and first and last characters are the same
L(i, j) = L(i + 1, j - 1) + 2
4)First and last characters are not the same and L(i + 1, j)< L(i, j - 1). L(i, j) = L(i, j - 1).
5)First and last characters are not the same and L(i + 1, j)>=L(i, j - 1). L(i, j) = L(i + 1, j).
We can observed that only in case 1,2 and 3, the character X[i] is included in the final result. We used a two-dimension auxiliary array to represent how the palindromic sub-sequence comes from.
value 0 for case 1,2,3; value 1 for case 4; value 2 for case 5.
With the auxiliary array Way. We can get the result as below:
Let two variables s=0 and e=n-1.
While s<=e
Loop
If Way[s][e]==0 Then X[s] should be included in the result and we store it in our result array.
Else if Way[s][e]==1 Then X[s] should not be include in the result and update e=e-1 (because our result comes from case 4).
Else if Way[s][e]==2 Then X[s] should not be include in the result and update s=s+1 (because our result comes from case 5).
The loop should be terminated when s>e. In that way we can get half part of the result and we can easily extend it to get the whole result.
Keep a backpointer as well as a value in your dynamic programming table for each cell. Then follow the traceback from the end of the table to reconstruct the subsequence.
The trick works like this:
save the reverse of your string in a temporary buffer
use the Longest Common Substring Algorithm to find the LCS.
Note that by definition of your second string, the LCS of both strings is the longest palindrome as well.
The below solution is pretty straight forward and requires no additional use of any other matrix.
Here we are just tracing back our path to generate the longest palindromic sub sequence.
int lps(char *str)
{
int n = strlen(str);
int i, j, cl;
int L[n][n];
for (i = 0; i < n; i++)
L[i][i] = 1;
for (cl=2; cl<=n; cl++)
{
for (i=0; i<n-cl+1; i++)
{
j = i+cl-1;
if (str[i] == str[j] && cl == 2)
L[i][j] = 2;
else if (str[i] == str[j])
L[i][j] = L[i+1][j-1] + 2;
else
L[i][j] = max(L[i][j-1], L[i+1][j]);
}
}
cout<<L[0][n-1]<<endl;
i = 0,j = n-1;
vector<char> result;
while(i<=j)
{
if(str[i]==str[j])
{
result.push_back(str[i]);
i++,j--;
}
else if(L[i][j-1]>L[i+1][j])
{
j--;
}
else
{
i++;
}
}
if(L[0][n-1]%2==0)
{
for(auto i = result.begin();i!=result.end();i++)
cout<<*i;
reverse(result.begin(),result.end());
for(auto i = result.begin();i!=result.end();i++)
cout<<*i;
}
else
{
for(auto i = result.begin();i!=result.end();i++)
cout<<*i;
reverse(result.begin(),result.end());
result.erase(result.begin());
for(auto i = result.begin();i!=result.end();i++)
cout<<*i;
}
}
A Java approach .Building the string from the LPS matrix generated during calculation of length of the palindromic sub-sequence.
private static void LongestPalindromicSubsequence(char a[])
{
int len=a.length;
int lps[][]=new int[len][len];
int l=1;
for(int i=0;i<len;i++)
{
lps[i][i]=1; //---------> Length of subsequence of string of length=1 is 1 <------------
}
for(int subsLen=2;subsLen<=len;subsLen++)
{
for( int i=0;i<(len-subsLen+1);i++)
{
int j=i+subsLen-1;
if(a[i]==a[j]&&subsLen==2)
{
lps[i][j]=2;
}
else
{
if(a[i]!=a[j])
{
lps[i][j]=Math.max(lps[i+1][j],lps[i][j-1]);
}
else
{
lps[i][j]=2+lps[i+1][j-1];
}
}
}
}
// System.out.println("Length of longest Palindromic subsequence: "+lps[0][len-1]);
printLongestPalindromicsubsequence(a,lps);
}
private static void printLongestPalindromicsubsequence(char[] a, int[][] lps)
{
int len=a.length;
int end=lps[0][len-1];
char str[]=new char[end+1];
str[end--]='\0';
int i=0,j=len-1;
while(end>=0&&i<=j)
{
if(a[i]==a[j])
{
str[end--]=a[i];
i++;
j--;
}
else
{
if(lps[i+1][j]>lps[i][j-1])
{
i++;
}
else
{
j--;
}
}
}
if(lps[0][len-1]%2!=0)
{
i=0;
int mid=lps[0][len-1]/2;
j=str.length-2;
while(j>mid)
{
str[i++]=str[j--];
}
}
else
{
i=0;
int mid=lps[0][len-1]/2;
j=str.length-2;
while(j>=mid)
{
str[i++]=str[j--];
}
}
for(i=0;i<str.length;i++)
System.out.print(str[i]);
}
A sample java implementation. Feel free to be brutal with your review comments.
public class LongestPalindrome {
public static void main(String... arguments) {
final String content = "GOBANANAS";
String palindrome = getLongestPalindrome(content);
System.out.println(palindrome);
}
private static String getLongestPalindrome(final String content) {
String lastPalindrome = "";
for (int lastIndex = content.length(); lastIndex >= 0; lastIndex--) {
for (int i = 0; i <= lastIndex; i++) {
String part = content.substring(i, lastIndex);
if (part.length() > lastPalindrome.length() && part.length() > 1) {
boolean isPalindrome = isPalindrome(part);
if (isPalindrome) {
lastPalindrome = part;
System.out.println(String.format("%s : %s", part, isPalindrome));
}
}
}
}
return lastPalindrome;
}
private static boolean isPalindrome(String string) {
String reverse = (new StringBuilder(string)).reverse().toString();
return (string.equals(reverse));
}
}

How do I efficiently determine the longest individual character palindrome in a given string?

Given a string of length N containing characters [A-Z], how do I determine the longest palindrome for an individual character?
I will illustrate this with an example:
Given string: JOHNOLSON
In analyzing the string, we find that we have a palindrome with the character O such that the string looks like JOHNOLSON. The palindrome for the O's is of length 7 essentially looking like O--O--O. Also, notice that there is a palindrome with N, but it is only of length 6.
Another example,
Given string: ABCJOHNOLSON gives the same result as above with a palindrome of the O's of length 7 looking like O--O--O.
However, with the given string ABCJOHNOLSONDA, the longest individual character palindrome is of length 14 with the character A looking like A------------A.
Other simple examples include:
ABA --> A-A (length 3)
ABAXYZ --> A-A (length 3)
ABAXYZA --> A---A (length 5), not length 7 because A-A---A is not a palindrome for the letter A.
Pay special attention to the last example because it illustrates one of the subtle nuances of the problem.
You can do it in linear time, it's described here with a code sample.
Here's what I came up with, I don't know how efficient it might be.
For every letter in the alphabet,
Find the first and last occurrence of this letter.
While the substring is not a palindrome for that letter (easy to check),
find the next letter on both sides so that every possible combination is
checked. Take the longest one and store it.
Take the longest one.
Definitely not optimal. Assumes input string is all lowercase.
using System;
using System.Collections.Generic;
public class LongestPalindrome
{
public int longest(string s)
{
Dictionary<char, List<int>> indices =
new Dictionary<char, List<int>>();
// find all indices for each letter
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (!indices.ContainsKey(c))
indices.Add(c, new List<int>());
indices[c].Add(i);
}
int max = Int32.MinValue;
for (int i = (int)'a'; i <= (int)'z'; i++)
{
char c = (char)i;
// in case a letter didn't appear at all in the input string
if (!indices.ContainsKey(c)) continue;
List<int> indexList = indices[c];
// in case a letter appeared only once in the input string
if (indexList.Count == 1) max = Math.Max(max, 1);
for (int j = 0; j < indexList.Count; j++)
{
for (int k = j + 1; k < indexList.Count; k++)
{
int dist = indexList[k] - indexList[j] + 1;
string sub = s.Substring(indexList[j], dist);
if (isPalendrome(sub, c))
max = Math.Max(max, dist);
}
}
}
return max;
}
bool isPalendrome(string s, char c)
{
int i = 0;
while(i < s.Length - 1 - i)
{
if (s[i] != c && s[s.Length - 1 - i] != c)
{
i++;
continue;
}
if (s[i] != s[s.Length - 1 - i]) return false;
i++;
}
return true;
}
}

Resources