There is a strange printer with the following two special properties:


	The printer can only print a sequence of the same character each time.
	At each turn, the printer can print new characters starting from and ending at any place and will cover the original existing characters.


Given a string s, return the minimum number of turns the printer needed to print it.

&nbsp;
Example 1:

Input: s = "aaabbb"
Output: 2
Explanation: Print "aaa" first and then print "bbb".


Example 2:

Input: s = "aba"
Output: 2
Explanation: Print "aaa" first and then print "b" from the second place of the string, which will cover the existing character 'a'.


&nbsp;
Constraints:


	1 &lt;= s.length &lt;= 100
	s consists of lowercase English letters.


class Solution(object):
    def strangePrinter(self, s):
        """
        :type s: str
        :rtype: int
        """
        # remove duplicate letters from s.
        tmp = []
        for c in s:
            if len(tmp) == 0 or tmp[-1] != c:
                tmp.append(c)
        s = "".join(tmp)

        _m = {}
        def _dp(i, j, background):
            if j < i:
                return 0
            elif i == j:
                return 1 if background != s[i] else 0
            elif (i, j, background) in _m:
                return _m[(i, j, background)]

            ans = len(s)

            # shrink s[i:j+1] to s[i_:j_+1] according to the background letter
            i_ = i + 1 if s[i] == background else i
            j_ = j - 1 if s[j] == background else j

            if s[i_] == s[j_]:
                # case "AxxxA" => best strategy is printing A first
                ans = _dp(i_ + 1, j_ - 1, s[i_]) + 1
            else:
                # otherwise, print first letter, try every possible print length
                for p in range(i_, j_ + 1):
                    # searching is needed only if s[p] == s[i_]
                    # e.g. s="ABCDEA"print 'A' on s[0:1] is equivalent to s[0:5]
                    if s[p] != s[i_]:
                        continue
                    l = _dp(i_, p, s[i_])
                    r = _dp(p + 1, j_, background)
                    ans = min(ans, l + r + 1)
            _m[(i, j, background)] = ans
            return ans

        return _dp(0, len(s) - 1, '')
class Solution {

public int strangePrinter(String s) {
    if (s.equals("")) return 0;
    int len = s.length();
    int[][] dp = new int[len][len];
    for (int i = 0; i < len; i++)
        dp[i][i] = 1;
    for (int l = 2; l <= len; l++) {
        for (int i = 0; i < len && l + i - 1 < len; i++) {
            int j = l + i - 1;
            dp[i][j] = dp[i][j - 1] + (s.charAt(i) == s.charAt(j) ? 0 : 1);
            for (int k = i + 1; k < j; k++) {
                if (s.charAt(k) == s.charAt(j)) {
                    dp[i][j] = Math.min(dp[i][j], dp[i][k - 1] + dp[k][j - 1]);
                }
            }
        }
    }
    return dp[0][len - 1];
}
}
class Solution {
public:
    int dp[101][101];
    int solve(string s,int i,int j)
    {
        if(i>j)
            return 0;
        if(dp[i][j]!=-1)
            return dp[i][j];
        int ans=0;
        while(i<j && s[i+1]==s[i])
            i++;
        while(i<j && s[j]==s[j-1])
        {
            j--;
        }
        ans=1+solve(s,i+1,j);
        for(int k=i+1;k<=j;k++)
        {
            if(s[k]==s[i])
            {
                int cnt=solve(s,i+1,k-1)+solve(s,k,j);
                ans=min(ans,cnt);
            }
        }
        return dp[i][j]=ans;
    }
    int strangePrinter(string s)
    {
        memset(dp,-1,sizeof(dp));
         return solve(s,0,s.size()-1);
    }
};
// if you like the solution plz upvote.
var strangePrinter = function(s) {
    if(!s) return 0;

    const N = s.length;    
    const state = Array.from({length:N}, () => Array.from({length:N}));
    
    for(let i = 0; i < N; i++) {
        // Printing one character always takes one attempt
        state[i][i] = 1;
    }
    
    const search = (i,j) => {
        if(state[i][j]) return state[i][j];
        
        state[i][j] = Infinity;
        for(let k = i; k < j; k++) {
            state[i][j] = Math.min(state[i][j], search(i,k) + search(k+1,j));
        }
        if(s[i] === s[j]) state[i][j]--;
        return state[i][j];
    }
    
    return search(0, N-1);
}
Strange Printer