zoukankan      html  css  js  c++  java
  • 判断一个字符串在至多删除k个字符后是否为回文串

    转自: http://www.careercup.com/question?id=6287528252407808

    问题描述:

    A k-palindrome is a string which transforms into a palindrome on removing at most k characters.
    Given a string S, and an interger K, print "YES" if S is a k-palindrome; otherwise print "NO".
    Constraints:
    S has at most 20,000 characters.
    0<=k<=30
    Sample Test Case#1:
    Input - abxa 1
    Output - YES
    Sample Test Case#2:
    Input - abdxa 1
    Output – No

    解答:懒得写了,下面这段通俗易懂,就先将就着看吧

    The question asks if we can transform the given string S into its reverse deleting at most K letters.
    We could modify the traditional Edit-Distance algorithm, considering only deletions, and check if this edit distance is <= K. There is a problem though. S can have length = 20,000 and the Edit-Distance algorithm takes O(N^2). Which is too slow.
    (From here on, I'll assume you're familiar with the Edit-Distance algorithm and its DP matrix)
    However, we can take advantage of K. We are only interested *if* manage to delete K letters. This means that any position more than K positions away from the main diagonal is useless because its edit distance must exceed those K deletions.
    Since we are comparing the string with its reverse, we will do at most K deletions and K insertions (to make them equal). Thus, we need to check if the ModifiedEditDistance is <= 2*K
    Here's the code:

       1:  int ModifiedEditDistance(const string& a, const string& b, int k) {
       2:      int i, j, n = a.size();
       3:      // for simplicity. we should use only a window of size 2*k+1 or 
       4:      // dp[2][MAX] and alternate rows. only need row i-1
       5:      int dp[MAX][MAX];
       6:      memset(dp, 0x3f, sizeof dp);    // init dp matrix to a value > 1.000.000.000
       7:      for (i = 0 ; i < n; i++)
       8:          dp[i][0] = dp[0][i] = i;
       9:   
      10:      for (i = 1; i <= n; i++) {
      11:          int from = max(1, i-k), to = min(i+k, n);
      12:          for (j = from; j <= to; j++) {
      13:              if (a[i-1] == b[j-1])            // same character
      14:                  dp[i][j] = dp[i-1][j-1];    
      15:              // note that we don't allow letter substitutions
      16:              
      17:              dp[i][j] = min(dp[i][j], 1 + dp[i][j-1]); // delete character j
      18:              dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]); // insert character i
      19:          }
      20:      }
      21:      return dp[n][n];
      22:  }
      23:  cout << ModifiedEditDistance("abxa", "axba", 1) << endl;  // 2 <= 2*1 - YES
      24:  cout << ModifiedEditDistance("abdxa", "axdba", 1) << endl; // 4 > 2*1 - NO
      25:  cout << ModifiedEditDistance("abaxbabax", "xababxaba", 2) << endl; // 4 <= 2*2 - YES

    We only process 2*K+1 columns per row. So this algorithm works in O(N*K) which is fast enough.

  • 相关阅读:
    Java实现 LeetCode 27 移除元素
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
  • 原文地址:https://www.cnblogs.com/xubenben/p/3398404.html
Copyright © 2011-2022 走看看