LintCode 253: Minimum Type Way (双序列DP好题)

253. Minimum Type Way

You are given a string only contains lower or upper English characters that you want to type.
At the beginning, the Capslock is off, it's at a state of lower characters, you are required that after typing it should still be at lower state.
There are three kinds operations:

  1. Type a character, the screen will print a character at corresponding state (lower or upper). You hit the keyboard once.
  2. Press Capslock, switch the state of the keyboard. You hit the keyboard once.
  3. Press Shift with some character, the screen will print a character at a opposite state. You hit the keyboard twice. e.g. It will print 'P' when you press Shift + 'p'.

Example

Input:
"Hello"
Output:
6

Clarification

The type steps:Shift + 'h', 'e', 'l', 'l', 'o'.

Notice

The length of the string is N, 1≤N≤10​5​​.

Input test data (one parameter per line)How to understand a testcase?

解法1:
这题想了好久。我开始的解法不对。参考的别人的思路。

这题难在有几种组合混在一起。对于每个字母,无论大写或小写,都可以通过按CAP键与否和按SHIFT键与否来实现。这种情况可以通过DP来解决,保证不会遗漏中间的情况。

双序列DP: upper[i]表示当前为第i个字符,CAP键按下时所需的最少按键,lower[i]表示当前为第i个字符,CAP键未按下时所需的最少按键。那么,

当第i个字符为大写字母时:
upper[i]如果由upper[i-1]来实现,其值直接加1即可。因为CAP键已经按下,不需再按SHIFT键,
upper[i]如果由lower[i-1]来实现,其值必须加2。因为CAP键未按下,必须要按下CAP键,再敲第i个字符。
lower[i]如果由upper[i-1]来实现,其值必须加2。因为CAP键已经按下,必须要再按CAP键消掉大写功能,再直接敲第i个字符。
lower[i]如果由lower[i-1]来实现,其值必须加2。因为CAP键未按下,必须要按SHIFT键来实现大写。

当第i个字符为小写字母时:
upper[i]如果由upper[i-1]来实现,其值必须加2。因为CAP键已经按下,必须再按SHIFT键来实现小写。
upper[i]如果由lower[i-1]来实现,其值必须加2。因为CAP键未按下,必须要按下CAP键,再敲第i个字符。
lower[i]如果由upper[i-1]来实现,其值必须加2。因为CAP键已经按下,必须要再按CAP键消掉大写功能,再直接敲第i个字符。
lower[i]如果由lower[i-1]来实现,其值直接加1即可。因为CAP键未按下,也不需要按SHIFT键就可以实现小写。

代码如下:

class Solution {
public:
    /**
     * @param str: the string you wanna print.
     * @return: return the minimum times you need to hit the keyboard.
     */
    int minimumTyping(string &str) {
        int n = str.size();
        vector<int> upper(n);
        vector<int> lower(n);
        
        if (isupper(str[0])) {
            upper[0] = 2;
            lower[0] = 2;
        } else {
            upper[0] = 2;
            lower[0] = 1;
        }

        for (int i = 1; i < n; ++i) {
            if (isupper(str[i])) {
                upper[i] = min(upper[i - 1] + 1, lower[i - 1] + 2);
                lower[i] = min(upper[i - 1] + 2, lower[i - 1] + 2);
            } else {
                upper[i] = min(upper[i - 1] + 2, lower[i - 1] + 2);
                lower[i] = min(upper[i - 1] + 2, lower[i - 1] + 1);
            }
        }
        
        return lower.back();
    }
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值