String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3054    Accepted Submission(s): 812


 

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

 

 

Sample Output

abb

 

 

Source

2019 Multi-University Training Contest 1

 

 

Recommend

We have carefully selected several similar problems for you:  6742 6741 6740 6739 6738 


OJ题号

HDU6586

简单题意

从原先字符串找到一个长度为n的子串,要满足给定的26个字母个数的上下界,且字典序最小。

正解思路

构造一个序列自动机nxt[i][j]表示i后面字符j的最近位置,因为要求字典序最小,所以我们对于每一个位置直接按字母顺序枚举,如果可以则check()立马填上,如果不可以继续往下走,一直找到长度为m即可。

check()细节:

  • 剩余的字母Ai在不超过Ri的情况下能构成n长度的串。
  • 原串剩余的字母Ai数量+已拿取字母Ai数量>=Li
  • 满足Li所需的长度小于剩余可添加长度
#include <bits/stdc++.h>
using namespace std;

const int N = 5e5+5;
typedef  long long LL;

int n,l[N],r[N];
struct Sequence
{
    char str[N];
    int nxt[N][30],num[N][30];
    int len;
    init()
    {

        len=strlen(str+1);
        for(int i=0; i<=len; i++)
        {
            for(int j=0; j<26; j++)
			{
				num[i][j]=0; 
				nxt[i][j]=-1 ;
			}
                
        }
        
    }

    void get()
    {
        for(int i=len; i>=1; i--)
        {
            for(int j=0; j<26; j++)
            {
                nxt[i-1][j]=nxt[i][j];
                num[i-1][j]=num[i][j];
            }
            nxt[i-1][str[i]-'a']=i;
            num[i-1][str[i]-'a']++;
        }
    }

    bool judge(char str2[]) //判断是否为其子序列,str2从1开始
    {
        int len2=strlen(str2+1);
        int p=0;
        for(int i=1; i<=len2; i++)
        {
            p=nxt[p][str2[i]-'a'];
            if(p==-1)
                return 0;
        }
        return 1;
    }
    void out()
    {
        for(int i=0; i<=len; i++)
        {
            for(int j=0; j<26; j++)
            {
                cout<<nxt[i][j]<<" ";
            }
            cout<<endl;
        }
    }




} s;
int num[30];
bool check(int pos,int cnt)
{
    //cout<<cnt<<" "<<char(c+'a')<<endl;
    LL sum=0,sum1=0;
    for(int j=0; j<26; j++)
    {

        if(num[j]+s.num[pos][j]<l[j])
            return 0;
        sum+=num[j]+max(0,min(r[j]-num[j],s.num[pos][j]));
        sum1+=max(0,l[j]-num[j]);

    }
    if(sum<n)
        return 0;
    if(sum1>n-cnt)
        return 0;
    return 1;
}
char res[N];
int main()
{

    while(~scanf("%s %d",s.str+1,&n))
    {
        s.init();
        s.get();
        for(int i=0; i<26; i++)
        {
            num[i]=0;
            scanf("%d%d",&l[i],&r[i]);
        }
        //s.out();

       
        int flag=0,ok=1;
        int pos=0;
        int cnt=0;
        while(pos<=s.len&&cnt<n)
        {
            flag=0;
            for(int j=0; j<26; j++)
            {
                //cout<<(char)(j+'a')<<" "<<s.nxt[pos][j]<<" "<<num[j]<<endl;
                num[j]++;
                if(s.nxt[pos][j]!=-1&&num[j]<=r[j]&&check(s.nxt[pos][j],cnt+1))
                {

                    flag=1;
                    res[cnt++]='a'+j;
                    pos=s.nxt[pos][j];
                    break;
                }
                num[j]--;
            }
            if(flag==0)
            {
                ok=0;
                break;
            }

        }
        res[n]='\0';

        if(ok==0)
        {
            printf("-1\n");
        }
        else
            printf("%s\n",res);

    }

    return 0;
}