Find if string is K-Palindrome or not - GeeksforGeeks


Find if string is K-Palindrome or not - GeeksforGeeks
Given a string, find out if the string is K-Palindrome or not. A k-palindrome string transforms into a palindrome on removing at most k characters from it.

If we carefully analyze the problem, the task is to transform the given string into its reverse by removing at most K characters from it. The problem is basically a variation of Edit Distance. We can modify the Edit Distance problem to consider given string and its reverse as input and only operation allowed is deletion. Since given string is compared with its reverse, we will do at most N deletions from first string and N deletions from second string to make them equal. Therefore, for a string to be k-palindrome, 2*N <= 2*K should hold true. Below are the detailed steps of algorithm - Process all characters one by one staring from either from left or right sides of both strings. Let us traverse from the right corner, there are two possibilities for every pair of character being traversed.
  1. If last characters of two strings are same, we ignore last characters and get count for remaining strings. So we recur for lengths m-1 and n-1 where m is length of str1 and n is length of str2.
  2. If last characters are not same, we consider remove operation on last character of first string and last character of second string, recursively compute minimum cost for the operations and take minimum of two values.
    • Remove last char from str1: Recur for m-1 and n.
    • Remove last char from str2: Recur for m and n-1.
int isKPalRec(string str1, string str2, int m, int n)
{
    // If first string is empty, the only option is to
    // remove all characters of second string
    if (m == 0) return n;
    // If second string is empty, the only option is to
    // remove all characters of first string
    if (n == 0) return m;
    // If last characters of two strings are same, ignore
    // last characters and get count for remaining strings.
    if (str1[m-1] == str2[n-1])
        return isKPalRec(str1, str2, m-1, n-1);
    // If last characters are not same,
    // 1. Remove last char from str1 and recur for m-1 and n
    // 2. Remove last char from str2 and recur for m and n-1
    // Take minimum of above two operations
    return 1 + min(isKPalRec(str1, str2, m-1, n), // Remove from str1
                   isKPalRec(str1, str2, m, n-1)); // Remove from str2
}
// Returns true if str is k palindrome.
bool isKPal(string str, int k)
{
    string revStr = str;
    reverse(revStr.begin(), revStr.end());
    int len = str.length();
    return (isKPalRec(str, revStr, len, len) <= k*2);
}

int isKPalDP(string str1, string str2, int m, int n)
{
    // Create a table to store results of subproblems
    int dp[m + 1][n + 1];
    // Fill dp[][] in bottom up manner
    for (int i = 0; i <= m; i++)
    {
        for (int j = 0; j <= n; j++)
        {
            // If first string is empty, only option is to
            // remove all characters of second string
            if (i == 0)
                dp[i][j] = j; // Min. operations = j
            // If second string is empty, only option is to
            // remove all characters of first string
            else if (j == 0)
                dp[i][j] = i; // Min. operations = i
            // If last characters are same, ignore last character
            // and recur for remaining string
            else if (str1[i - 1] == str2[j - 1])
                dp[i][j] = dp[i - 1][j - 1];
            // If last character are different, remove it
            // and find minimum
            else
             dp[i][j] = 1 + min(dp[i - 1][j], // Remove from str1
                             dp[i][j - 1]); // Remove from str2
        }
    }
    return dp[m][n];
}
// Returns true if str is k palindrome.
bool isKPal(string str, int k)
{
    string revStr = str;
    reverse(revStr.begin(), revStr.end());
    int len = str.length();
    return (isKPalDP(str, revStr, len, len) <= k*2);
}
http://www.geeksforgeeks.org/find-if-string-is-k-palindrome-or-not-set-2/
The idea is to find the longest palindromic subsequence of the given string. If the difference between longest palindromic subsequence and the original string is less than equal to k, then the string is k-palindrome else it is not k-palindrome.
For example, longest palindromic subsequence of string abcdeca is acdca(or aceca). The characters which do not contribute to longest palindromic subsequence of the string should be removed in order to make the string palindrome. So on removing b and d (or e) from abcdeca, string will transform into a palindrome.
Longest palindromic subsequence of a string can easily be found using LCS. Following is the two step solution for finding longest palindromic subsequence that uses LCS.
  1. Reverse the given sequence and store the reverse in another array say rev[0..n-1]
  2. LCS of the given sequence and rev[] will be the longest palindromic sequence.
Auxiliary space used by the program is O(n2). It can further be reduced to O(n) by using Space Optimized Solution of LCS.
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
int lcs( string X, string Y, int m, int n )
{
    int L[m + 1][n + 1];
    /* Following steps build L[m+1][n+1] in bottom up
        fashion. Note that L[i][j] contains length of
        LCS of X[0..i-1] and Y[0..j-1] */
    for (int i = 0; i <= m; i++)
    {
        for (int j = 0; j <= n; j++)
        {
            if (i == 0 || j == 0)
                L[i][j] = 0;
            else if (X[i - 1] == Y[j - 1])
                L[i][j] = L[i - 1][j - 1] + 1;
            else
                L[i][j] = max(L[i - 1][j], L[i][j - 1]);
        }
    }
    // L[m][n] contains length of LCS for X and Y
    return L[m][n];
}
// find if given string is K-Palindrome or not
bool isKPal(string str, int k)
{
    int n = str.length();
    // Find reverse of string
    string revStr = str;
    reverse(revStr.begin(), revStr.end());
    // find longest palindromic subsequence of
    // given string
    int lps = lcs(str, revStr, n, n);
    // If the difference between longest palindromic
    // subsequence and the original string is less
    // than equal to k, then the string is k-palindrome
    return (n - lps <= k);
}

If we carefully analyze the problem, the task is to transform the given string into its reverse by removing at most K characters from it. The problem is basically a variation of Edit Distance. We can modify the Edit Distance problem to consider given string and its reverse as input and only operation allowed is deletion. Since given string is compared with its reverse, we will do at most N deletions from first string and N deletions from second string to make them equal. Therefore, for a string to be k-palindrome, 2*N <= 2*K should hold true. Below are the detailed steps of algorithm - Process all characters one by one staring from either from left or right sides of both strings. Let us traverse from the right corner, there are two possibilities for every pair of character being traversed.
  1. If last characters of two strings are same, we ignore last characters and get count for remaining strings. So we recur for lengths m-1 and n-1 where m is length of str1 and n is length of str2.
  2. If last characters are not same, we consider remove operation on last character of first string and last character of second string, recursively compute minimum cost for the operations and take minimum of two values.
    • Remove last char from str1: Recur for m-1 and n.
    • Remove last char from str2: Recur for m and n-1.
This problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, re-computations of same subproblems can be avoided by constructing a temporary array that stores results of subproblems .

// find if given string is K-Palindrome or not
int isKPalDP(string str1, string str2, int m, int n)
{
    // Create a table to store results of subproblems
    int dp[m + 1][n + 1];
    // Fill dp[][] in bottom up manner
    for (int i = 0; i <= m; i++)
    {
        for (int j = 0; j <= n; j++)
        {
            // If first string is empty, only option is to
            // remove all characters of second string
            if (i == 0)
                dp[i][j] = j; // Min. operations = j
            // If second string is empty, only option is to
            // remove all characters of first string
            else if (j == 0)
                dp[i][j] = i; // Min. operations = i
            // If last characters are same, ignore last character
            // and recur for remaining string
            else if (str1[i - 1] == str2[j - 1])
                dp[i][j] = dp[i - 1][j - 1];
            // If last character are different, remove it
            // and find minimum
            else
             dp[i][j] = 1 + min(dp[i - 1][j], // Remove from str1
                             dp[i][j - 1]); // Remove from str2
        }
    }
    return dp[m][n];
}
// Returns true if str is k palindrome.
bool isKPal(string str, int k)
{
    string revStr = str;
    reverse(revStr.begin(), revStr.end());
    int len = str.length();
    return (isKPalDP(str, revStr, len, len) <= k*2);
}

If we carefully analyze the problem, the task is to transform the given string into its reverse by removing at most K characters from it. The problem is basically a variation of Edit Distance. We can modify the Edit Distance problem to consider given string and its reverse as input and only operation allowed is deletion. Since given string is compared with its reverse, we will do at most N deletions from first string and N deletions from second string to make them equal. Therefore, for a string to be k-palindrome, 2*N <= 2*K should hold true. Below are the detailed steps of algorithm - Process all characters one by one staring from either from left or right sides of both strings. Let us traverse from the right corner, there are two possibilities for every pair of character being traversed.
  1. If last characters of two strings are same, we ignore last characters and get count for remaining strings. So we recur for lengths m-1 and n-1 where m is length of str1 and n is length of str2.
  2. If last characters are not same, we consider remove operation on last character of first string and last character of second string, recursively compute minimum cost for the operations and take minimum of two values.
    • Remove last char from str1: Recur for m-1 and n.
    • Remove last char from str2: Recur for m and n-1.
// find if given string is K-Palindrome or not
int isKPalRec(string str1, string str2, int m, int n)
{
    // If first string is empty, the only option is to
    // remove all characters of second string
    if (m == 0) return n;
    // If second string is empty, the only option is to
    // remove all characters of first string
    if (n == 0) return m;
    // If last characters of two strings are same, ignore
    // last characters and get count for remaining strings.
    if (str1[m-1] == str2[n-1])
        return isKPalRec(str1, str2, m-1, n-1);
    // If last characters are not same,
    // 1. Remove last char from str1 and recur for m-1 and n
    // 2. Remove last char from str2 and recur for m and n-1
    // Take minimum of above two operations
    return 1 + min(isKPalRec(str1, str2, m-1, n), // Remove from str1
                   isKPalRec(str1, str2, m, n-1)); // Remove from str2
}
// Returns true if str is k palindrome.
bool isKPal(string str, int k)
{
    string revStr = str;
    reverse(revStr.begin(), revStr.end());
    int len = str.length();
    return (isKPalRec(str, revStr, len, len) <= k*2);
}
Solving K-Palindrome problem using Edit distance algorithm | coding hangover
http://xiaohuiliucuriosity.blogspot.com/2015/03/k-palindrome.html
O(kn)Any position more than K positions away from the main diagonal is useless because its edit distance must exceed those K deletions. We only process 2*K+1 columns per row, k columns from the diagonal on each side.
int ModifiedEditDistance(const string& a, const string& b, int k) {
    int i, j, n = a.size();
    // for simplicity. we should use only a window of size 2*k+1 or
    // dp[2][MAX] and alternate rows. only need row i-1
    int dp[MAX][MAX];
    memset(dp, 0x3f, sizeof dp);    // init dp matrix to a value > 1.000.000.000
    for (i = 0 ; i < n; i++)
        dp[i][0] = dp[0][i] = i;
    for (i = 1; i <= n; i++) {
        int from = max(1, i-k), to = min(i+k, n);
        for (j = from; j <= to; j++) {
            if (a[i-1] == b[j-1])           // same character
                dp[i][j] = dp[i-1][j-1];   
            // note that we don't allow letter substitutions
            dp[i][j] = min(dp[i][j], 1 + dp[i][j-1]); // delete character j
            dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]); // insert character i
        }
    }
    return dp[n][n];
}

This can be solved using Edit distance dynamic programming algorithm. Edit distance DP algorithm can be used to find the minimum operations required to convert a source string  to destination string. The operations can be either addition or deletion of characters.
The K-palindrome problem can be solved using Edit distance algorithm by checking if the minimum operation required to convert the input string to its reverse.
Let editDistance(source,destination) be the function which takes source string and destination string and returns the minimum operations required to convert the source string to destination string.
A string S is K-palindrome if editDistance(S,reverse(S))<=2*K
This is because we can transform the given string S into its reverse by deleting  K letters and then inserting K letters.
This will be more clear with an example.
Let S=madtam and K=1.
To convert it into reverse of S, i.e matdam first we have to remove the character at index 3 ( 0 based index) in S.
Now the intermediate string is madam . Then we have to insert the character t at index 2 in the intermediate string to get “matdam” which is the reverse of string s.
If you look carefully you will know that the intermediate string “madam” is the palindrome that is obtained by removing k=1 characters.
O(n^2)
Key: s is k-palindrome <=> editDistance(s, reverse(s)) <= 2k
editDistance is O(n^2) using DP.
https://linzhongzl.wordpress.com/2013/11/25/k-palindrome/
public static boolean isKPalindrome(String source, int k){
    return k == editDistance(source)/2;
}
public static int editDistance(String source){
    int n= source.length();
    int[][] distance=new int[n+1][n+1];
    for(int i=0;i<=n;i++){
        distance[i][0]=i;
    }
    for(int j=0;j<=n;j++){
        distance[0][j]=j;
    }
    for(int j=1;j<=n;j++){
      for(int i=1;i<=n;i++){
        if(source.charAt(i-1)==source.charAt(n-1-(j-1))){
            distance[i][j]=distance[i-1][j-1];
        }
        else{
            distance[i][j]= Math.min((distance[i-1][j]+1),(distance[i][j-1]+1));
        }
      }
    }
    return(distance[n][n]);
  }
public static void main(String[] args) {
    System.out.println(isKPalindrome("abaxbabax", 2));
}

http://xiaohuiliucuriosity.blogspot.com/2015/03/k-palindrome.html
http://stackoverflow.com/questions/20892506/determine-if-a-given-string-is-a-k-palindrome
O(2^N)
Change string to char array => subString in java 8 is O(n) now - not O(1).
bool isKPalindrome(string s, int k) {
    if (s.size() <= 1)
        return true;
     
    if (0 == k)
        return s[0] == s[s.size() - 1] && isKPalindrome(s.substr(1, s.size() - 2), k);
     
    if (s[0] == s[s.size() - 1])
        return isKPalindrome(s.substr(1, s.size() - 2), k);
    else
        return isKPalindrome(s.substr(0, s.size() - 1), k - 1) || isKPalindrome(s.substr(1, s.size() - 1), k - 1);
}
http://www.quora.com/A-k-palindrome-is-a-string-which-transforms-into-a-palindrome-on-removing-at-most-k-characters-from-it-Given-a-string-S-and-an-interger-K-find-whether-S-is-a-k-palindrome-or-not-Constraints-S-has-at-most-20-000-characters-and-0-k-30
http://www.geeksforgeeks.org/?p=12998
Dynamic Programming | Set 4 (Longest Common Subsequence)
1) Optimal Substructure: 
Let the input sequences be X[0..m-1] and Y[0..n-1] of lengths m and n respectively. And let L(X[0..m-1], Y[0..n-1]) be the length of LCS of the two sequences X and Y. Following is the recursive definition of L(X[0..m-1], Y[0..n-1]).
If last characters of both sequences match (or X[m-1] == Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2])
If last characters of both sequences do not match (or X[m-1] != Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = MAX ( L(X[0..m-2], Y[0..n-1]), L(X[0..m-1], Y[0..n-2])
  /* Returns length of LCS for X[0..m-1], Y[0..n-1] */
  int lcs( char[] X, char[] Y, int m, int n )
  {
    if (m == 0 || n == 0)
      return 0;
    if (X[m-1] == Y[n-1])
      return 1 + lcs(X, Y, m-1, n-1);
    else
      return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
  }

  /* Returns length of LCS for X[0..m-1], Y[0..n-1] */
  int lcs( char[] X, char[] Y, int m, int n )
  {
    int L[][] = new int[m+1][n+1];
    /* Following steps build L[m+1][n+1] in bottom up fashion. Note
         that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */
    for (int i=0; i<=m; i++)
    {
      for (int j=0; j<=n; j++)
      {
        if (i == 0 || j == 0)
            L[i][j] = 0;
        else if (X[i-1] == Y[j-1])
            L[i][j] = L[i-1][j-1] + 1;
        else
            L[i][j] = max(L[i-1][j], L[i][j-1]);
      }
    }
  return L[m][n];
  }
Read full article from Find if string is K-Palindrome or not - GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts