2019HDU多校第一场 1009 String

傷城~ 2021-11-27 00:44 416阅读 0赞

Problem Description

Tom has a string containing only lowercase letters. He wants to choose a subsequence of the string whose length is k and lexicographical order is the smallest. It’s simple and he solved it with ease.
But Jerry, who likes to play with Tom, tells him that if he is able to find a lexicographically smallest subsequence satisfying following 26 constraints, he will not cause Tom trouble any more.
The constraints are: the number of occurrences of the ith letter from a to z (indexed from 1 to 26) must in [Li,Ri].
Tom gets dizzy, so he asks you for help.

Input

The input contains multiple test cases. Process until the end of file.
Each test case starts with a single line containing a string S(|S|≤105)and an integer k(1≤k≤|S|).
Then 26 lines follow, each line two numbers Li,Ri(0≤Li≤Ri≤|S|).
It’s guaranteed that S consists of only lowercase letters, and ∑|S|≤3×105.

Output

Output the answer string.
If it doesn’t exist, output −1.

Sample Input

aaabbb 3 0 3 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

题意:给一个母串,给出每个字符出现次数的上下限,求长度为K的、满足次数要求的子串

思路:一位一位的求答案串,对每一位添加上去之后,判断剩下的串能不能满足条件

  1. #include<vector>
  2. #include<cstdio>
  3. #include<iostream>
  4. #include<cstring>
  5. using namespace std;
  6. const int M=1e5+50;
  7. int k,n,cnt[M][50],last,ans,l[M],used[M],r[M];
  8. char s[M],res[M];
  9. vector<int> g[26];
  10. int main(){
  11. while(scanf("%s%d",s,&k)!=EOF){
  12. memset(used,0,sizeof(used));
  13. for(int i=0;i<26;i++){
  14. scanf("%d%d",l+i,r+i);
  15. g[i].clear();
  16. }
  17. n=strlen(s);
  18. for(int i=0;i<=n+1;i++)for(int j=0;j<26;j++)cnt[i][j]=0;
  19. for(int i=n-1;i>=0;i--)for(int j=0;j<26;j++)cnt[i][j]=cnt[i+1][j]+(s[i]=='a'+j);
  20. for(int i=0;i<n;i++)g[s[i]-'a'].push_back(i);
  21. vector<int>::iterator head[26];
  22. for(int i=0;i<26;i++)head[i]=g[i].begin();
  23. ans=last=-1;
  24. for(int i=0;i<k;i++){
  25. int f1=0;
  26. for(int j=0;j<26;j++){
  27. if(used[j]==r[j])continue;
  28. while(head[j]!=g[j].end()&&(*head[j])<=last)head[j]++;
  29. if(head[j]==g[j].end())continue;
  30. used[j]++;
  31. int pos=*head[j],sum1=0,sum2=0,flag=1;
  32. for(int t=0;t<26;t++){
  33. if(cnt[pos+1][t]+used[t]<l[t])flag=0;
  34. sum1+=max(l[t]-used[t],0);
  35. sum2+=min(cnt[pos+1][t],r[t]-used[t]);
  36. }
  37. if(sum1>k-i-1||sum2<k-i-1)flag=0;
  38. if(!flag)used[j]--;
  39. else{
  40. res[i]='a'+j;
  41. f1=1;
  42. last=pos;
  43. break;
  44. }
  45. }
  46. if(!f1){
  47. printf("-1\n");
  48. ans=1;
  49. break;
  50. }
  51. }
  52. if(ans==-1){//如果有答案
  53. res[k]=0;
  54. printf("%s\n",res);
  55. }
  56. }
  57. return 0;
  58. }

发表评论

表情:
评论列表 (有 0 条评论,416人围观)

还没有评论,来说两句吧...

相关阅读