strange printer
There is a strange printer with the following two special requirements:
- 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 places, and will cover the original existing characters.
Given a string consists of lower English letters only, your job is to count the minimum number of turns the printer needed in order to print it.
Example 1:
Input: "aaabbb" Output: 2 Explanation: Print "aaa" first and then print "bbb".
Example 2:
Input: "aba" Output: 2 Explanation: Print "aaa" first and then print "b" from the second place of the string, which will cover the existing character
Hint: Length of the given string will not exceed 100.
本人只想出了时间复杂度是O(n3)的解题方法,由于在数据量不大(100以内),所以在leetcode上也能过了,如果还有其它更好的方法,欢迎交流。
解题思路:
用二维数组 v[begin][end] 表示字符串 s 的子串(下标从 begin 到 end)所需要最少的打印次数。考虑如何得到 v[begin][end+1],只有两种可能:
1. s[end+1] 字符单独打印,此时 v[begin][end+1] = v[begin][end] + 1。
2. s[end+1] 字符连着前面的某个相同的字符一起打印,由于字符串可能出现多个相同的字符,所以假设这些字符的下标分别为 t0,t1t2······ tn,那么得到式子
v[begin][end+1] = min (v[begin][t0] + v[t0+1][end],
v[begin][t1] + v[t1+1][end],
v[begin][t2] + v[t2+1][end]
...........
v[begin][tn] + v[tn+1][end])
(如果 s[end+1] 字符连着前面的字符 s[t] 一起打印的话,要想得到最少打印次数,那么下标从 t+1 开始到 end 结束之间的每一个字符必定不能与下标是 t 之前的字符一起连着打印)
下面是代码:
int strangePrinter(string s) { int n = s.length(); if (n == 0) return 0; vector<vector<int> > v(n, vector<int>(n, 0)); v[0][0] = 1; int tmp; for (int j = 1; j < n; ++j) { for (int i = 0; i <= j; ++i) { if (i == j) { v[i][j] = 1; continue; } v[i][j] = v[i][j-1] + 1; for (int t = i; t <= j-1; ++t) { tmp = 0; if (s[t] == s[j]) { tmp += v[i][t]; if (t < j-1) tmp += v[t+1][j-1]; v[i][j] = min(v[i][j], tmp); } } } } return v[0][n-1]; }