ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #710 (Div. 3) G. Maximize the Remaining String (字符串,枚举,序列自动机)

2021-03-29 11:02:15  阅读:206  来源: 互联网

标签:suf cur int Codeforces len 710 nx need String



  • 题意:给你一个字符串,要求删去重复的字母,使得只剩下一个字母,那么最后的得到的字符串每个字母都只出现一次,问你怎么操作是的最后的字符串字典序最大.

  • 题解:我们先用后缀和处理每个字母出现的次数,然后再用序列自动机预处理一下,首先我们先得到删去重复字母后字符串的长度,然后再去枚举.

    因为要求字典序最大,所以对于每个位置,我们枚举\(['z','a']\),\(cur\)表示当前指针在\(s\)中的所在位置,即\(cur\)之前的元素我们都不要了,如果你了解序列自动机的话,这并不难想.那么对于当前位置\(cur\),我们得到序列自动机\(nx\)数组找到我们当前枚举到的字母的所在位置,因为我们想把我们当前所枚举到的字母放入答案,所以,\([cur,nx[cur][need]-1]\),这段区间的所有字母都需要删去,那么我们怎么知道能不能删呢?这是我们之前处理的后缀和的作用就体现出来了,我们可以枚举\(['a','z']\)每个字母,先看他们在\([cur,nx[cur][need]]\)中是否出现,如果出现,那么在\([nx[cur][need]+1,len(s)]\)这段区间中,它至少要出现一次,那么我们就可以将它删去,这里记个\(flag\)判断一下就好.

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int suf[N][26];
    int nx[N][26];
    int cnt[N],used[N];
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	int _;
    	cin>>_;
    	while(_--){
    		string s;
    		cin>>s;
    		int len=(int)s.size();
    		s=" "+s;
    		string ans="";
    
    		rep(i,0,25){
    			cnt[i]=used[i]=0;
    			suf[len+1][i]=0;
    			nx[len+1][i]=0;
    		}
    
    		per(i,len,1){
    			cnt[s[i]-'a']++;
    			rep(j,0,25) suf[i][j]=suf[i+1][j];
    			suf[i][s[i]-'a']++;
    		}
    		per(i,len,1){
    			rep(j,0,25) nx[i][j]=nx[i+1][j];
    			nx[i][s[i]-'a']=i;
    		}
    		int len_=0;
    		rep(i,0,25) len_+=(cnt[i]!=0);
    
    		int cur=1;
    		rep(i,1,len_){
    			per(need,25,0){
    				if(!used[need] && nx[cur][need]){
    					int nxt=nx[cur][need];
    					int flag=1;
    					rep(abd,0,25){
    						if(need==abd) continue;
    						if(!used[abd] && suf[cur][abd]-suf[nxt+1][abd]){
    							flag&=(suf[nxt+1][abd]>0);
    						}
    					}
    					if(flag){
    						used[need]=1;
    						ans.pb(need+'a');
    						cur=nxt+1;
    						break;
    					}
    				}
    			}
    		}
    
    		cout<<ans<<'\n';
    
    	}
    
        return 0;
    }
    

标签:suf,cur,int,Codeforces,len,710,nx,need,String
来源: https://www.cnblogs.com/lr599909928/p/14591483.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有