1520. 最多的不重叠子字符串(贪心+区间)

1520. 最多的不重叠子字符串(贪心+区间)_第1张图片
先统计出每个字母的起始与终止位置,
然后对它们进行扩展并去掉不合法的。比如abab, a为【0,2】。而b为【1,3】,扩展为【0,3】;再比如ababa, a为【0,4】,b为【1,3】,显然b是不合法的,可以将b 从集合中删掉,也可以将b 扩展为a

处理之后所有字串均合法,且不会出现交叉重叠,即形如【0,2】,【1,3】。 但允许一个串包含另一个串。
经过这样处理之后,返回的串的个数肯定是固定了的(不存在交叠的串),只需要利用贪心优先返回最短的串(因为存一个大串,包含小串的可能)。这里,可以将以串的终点进行热排序,返回终点最小的(因为只存在一个串包含小串的可能),返回终点最小的,就是返回长度最小的。

不用贪心的话,可以在对子串进行扩展后,将包含小串的大串删掉,返回小串(串扩展之后只存在 大串套小串,和不同串 并列放置的情况)

class Solution {
public:
    static bool cmp(vector<int>a,vector<int>b){
        return a[1]<b[1];
    }
    vector<string> maxNumOfSubstrings(string s) {
        vector<vector<int>>intervals(26,vector<int>(2,-1));
        for(int i=0;i<s.size();i++){
            if(intervals[s[i]-'a'][0]==-1){
                intervals[s[i]-'a'][0]=i;
                intervals[s[i]-'a'][1]=i;
                
            }
            else
                 intervals[s[i]-'a'][1]=i;
        }  
            vector<vector<int>>_intervals;

        for(int i = 0; i < 26; i++){
            if(intervals[i][0] == -1) continue;
            int flag=1;
            for(int j = intervals[i][0]+1; j < intervals[i][1]; j++){
                if( (intervals[s[j] - 'a'][0] < intervals[i][0] )){
                    flag=0; break;
                }
                else 
                    intervals[i][1] = max( intervals[i][1] ,intervals[s[j] - 'a'][1]);
            }
            if(flag ) _intervals.push_back(intervals[i]);     
        }
    
          //按照区间终结点,从小到大排序
        sort(_intervals.begin(), _intervals.end(),cmp);   
        vector<string> x;
        int end = -1;
        int start=0;
        for (int i=0; i < _intervals.size(); ++i) {
            //如果区间的起点,小于上一个区间的终点,说明有交集,要删除
            if (_intervals[i][0] > end) {      
                //没有交集,更新end
                end = _intervals[i][1];
                start=_intervals[i][0];
                x.push_back(s.substr(start,end-start+1));
                } 
            
        }
        return x;
    }
 

};

你可能感兴趣的:(leetcode)