先统计出每个字母的起始与终止位置,
然后对它们进行扩展并去掉不合法的。比如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;
}
};