Leetcode每日一题打卡

面试题17.13.回复空格

原题

要找到最少的未确定的字符数,使用动态规划的方法,用数组dp[i]来确定截止位置i的未确定字符数。遍历无空格语句sentence,对于第i个位置,未确定字符数为dp[i]=dp[i-1]+1,然后再判断,是否存在j,使得区间(i,j)中的字符串存在于字符串表(即字典)中,如果存在,那么dp[i]=min(dp[i],dp[j-1]),最后返回dp[sentence.size()]。
那么,现在的问题是,如何确定一个字符串是否在字典中呢?这里采用Rabin-Karp字符串编码的方式,赋予每个字符串自己的数值,使用并查集进行查找。代码如下:

class Solution {
public:
    using LL=long long;
    static const LL MOD=1LL<<31-1;//用于取余
    static const LL Base=31;//31进制
    int getHash(const string& s) { //得到唯一编码
        LL hashValue=0;
        for(int i=s.size()-1;i>=0;i--) {
            hashValue=hashValue*Base+s[i]-'a'+1;//按Base进制转化成十进制
            hashValue%=MOD;//避免因为字符串太长而溢出,取余
            //只要MOD够大……不同字符串取余撞上的可能性就很小
        }
        return hashValue;
    }
    int respace(vector<string>& dictionary, string sentence) {
        unordered_set<LL> hashMap;
        int n=dictionary.size();
        for(int i=0;i<n;i++) {//将字典里的单词转化为十进制数存在并查集中
            hashMap.insert(getHash(dictionary[i]));
        }
        vector<int> dp(sentence.length()+1,sentence.length());//动态规划数组
        dp[0]=0;
        for(int i=1;i<=sentence.length();i++) {
            dp[i]=dp[i-1]+1;
            LL hash_value=0;
            for(int j=i;j>=1;j--) {//每一个字符向前查找
                //计算第j到第i个数的编码值
                hash_value=hash_value*Base+(int)(sentence[j-1]-'a')+1;
                hash_value%=MOD;
                if(hashMap.find(hash_value)!=hashMap.end()) {//编码值在并查集中
                    //未定义的最小字符数
                    dp[i]=min(dp[i],dp[j-1]);
                }
            }
        }
        return dp[sentence.length()];
    }
};

时间复杂度O(|dictionary|+n2),空间复杂度O(n+p),其中,n为sentence的长度,p为字典中单词个数。
官答还有另一种解法:字典树方法,来解决查找字符串问题。

你可能感兴趣的:(Leetcode每日一题打卡,动态规划类题型)