Palindrome

Table of Contents

1 132. Palindrome Partitioning II

First, construct a Palindrome table. The algorithm is O(n2), but I have to use arrays instead of set to make it constant order of faster to pass the test cases.

class Solution {
public:
  int minCut(string s) {
    if (s.empty()) return 0;
    if (s.size() == 1) return 0;
    // calculate P[i,j] = true | false
    // more specifically, m[j][i] = true | false, meaning for all palindrome ends at j
    // m[j] => set(0-j)
    // std::unordered_map<int, std::unordered_set<int> > Pal;
    int size = s.size();

    vector<std::unordered_set<int> > Pal(size);

    int middle = 0;
    // how to calculate: middle from 0 - end
    // middle on number
    for (middle=0;middle<size;middle++) {
      int i = middle;
      int j = middle;
      while (i >= 0 && j < size) {
        if (s[i] == s[j]) {
          Pal[j].insert(i);
          i--;j++;
        } else {
          break;
        }
      }
    }
    for (middle=0;middle<size;middle++) {
      int i = middle;
      int j = middle+1;
      while (i >= 0 && j < size) {
        if (s[i] == s[j]) {
          Pal[j].insert(i);
          i--;j++;
        } else {
          break;
        }
      }
    }

    // start from (0,1), the the res[i], for each m[j]
    vector<int> res(size);
    for (int i=0;i<size;i++) {
      res[i] = i;
    }
    for (int j=0;j<size;j++) {
      for (int i : Pal[j]) {
        assert(i <= j);
        if (i == 0) {
          res[j] = std::min(0, res[j]);
        } else {
          res[j] = std::min(res[i-1] + 1, res[j]);
        }
        
      }
    }
    return res[size-1];
  }
};

This is a modification of another computing of Pal table. It is still slow due to use of set.

    vector<std::unordered_set<int> > inv_pal(size);

    for (int i=size-1;i>=0;i--) {
      for (int j=i;j<size;j++) {
        if (s[i] == s[j] && (j-i<2 || inv_pal[i+1].count(j-1) == 1)) {
          inv_pal[i].insert(j);
        }
      }
    }

Finally this one using the original algorithm but using arrays is fast.

class Solution3 {
public:
  int minCut(string s) {
    if (s.empty()) return 0;
    if (s.size() == 1) return 0;
    int size = s.size();
    int middle = 0;


    vector<vector<bool> > vpal(size, vector<bool>(size, false));
    for (middle=0;middle<size;middle++) {
      int i = middle;
      int j = middle;
      while (i >= 0 && j < size) {
        if (s[i] == s[j]) {
          vpal[j][i] = true;
          // Pal[j].insert(i);
          i--;j++;
        } else {
          break;
        }
      }
    }
    for (middle=0;middle<size;middle++) {
      int i = middle;
      int j = middle+1;
      while (i >= 0 && j < size) {
        if (s[i] == s[j]) {
          vpal[j][i] = true;
          // Pal[j].insert(i);
          i--;j++;
        } else {
          break;
        }
      }
    }
    vector<int> res(size);
    for (int i=0;i<size;i++) {
      res[i] = i;
    }
    for (int j=0;j<size;j++) {
      for (int i=0;i<size;i++) {
        if (vpal[j][i]) {
          if (i == 0) {
            res[j] = std::min(0, res[j]);
          } else {
            res[j] = std::min(res[i-1] + 1, res[j]);
          }
        }
      }
    }
    return res[size-1];
  }
};