原题:Gym-100971M
题意:
给一个k,一个字符串,问你可以找到最少多少个子串组成这个字符串,且每个子串包含恰好k个不同字母
第i个输出对应的字符串为前i长度原字符串
解析:
刚开始的时候被最少唬住了,后来才知道和最少也没多大关系
遍历到i个字母的时候,取最后面一个不同字符为k的一个串,就可以从前面的dp加一转化过来
当然,还有一种情况就是有多个不同字符为k的子串,…abc和..aabc
那么假设前面可以(不为-1),在后面符合要求(==k)的情况下把第一个a加到前面可能就会变多,不是最少了
如果前面不行,我们为了不输出-1,可能把第一个a加过去
代码:
D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int num[30];
int dp[200009];
int main(){
int k=read();
string x;cin>>x;int n=x.length();x=' '+x;
int sum=0;int l=1;
for(int i=1;i<=n;i++){
num[x[i]-'a']++;if(num[x[i]-'a']==1)sum++;
if(sum<k){ dp[i]=-1;continue;}
while(l<i&&sum>k){l++,num[x[l-1]-'a']--;if(num[x[l-1]-'a']==0)sum--;}
while(dp[l-1]==-1&&num[x[l]-'a']>1){
num[x[l]-'a']--;l++;
}
if(dp[l-1]==-1)dp[i]=-1;
else dp[i]=dp[l-1]+1;
}
for(int i=1;i<=n;i++){
printf("%d%c",dp[i],i==n?'\n':' ');
}
}