zoukankan      html  css  js  c++  java
  • [SNOI2019]字符串

    Luogu5329

    设删掉第(i)个字符之后得到的字符串为(s_i) , 请按照字典序对(s_1,s_2,……,s_n)从小到大排序。若两个字符串相等,则认为编号小的字符串字典序更小。

    考虑删掉第(i)位和第(j)位,其首尾相等,所以只要考虑(s[i+1,j])(s[i,j-1])的大小就行了。

    考虑写这样一个(cmp)函数,它的格式已经是固定了的,那么关键是需要预处理出某一段区间是相等的

    (f[i])表示(i)位置之后,第一个(s[i]!=s[i+1])的位置

    (if(f[i]>=j)) 中间串相等,编号小的在前
    (if(f[i]<j)) 比较这第一个不相同的位置的大小

    详见代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #define Debug(x) cout<<#x<<"="<<x<<endl
    #define rank Rank
    using namespace std;
    typedef long long LL;
    const int INF=1e9+7;
    inline LL read(){
        register LL x=0,f=1;register char c=getchar();
        while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
        while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
        return f*x;
    }
    
    const int N=1e6+5;
    
    int same[N],rank[N],n;
    char s[N];
    
    inline bool cmp(int a,int b){
    	if(a<b){
    		if(same[a]>=b) return 1;
    		return s[same[a]+1]<s[same[a]];
    	}
    	else return !cmp(b,a);//我觉得这样比较好,就固定了格式只有一种
    	/*else{
    		if(same[b]>=a) return 0;
    		return s[same[b]]<s[same[b]+1];
    	}*/
    }
    
    int main(){
    	n=read();scanf("%s",(s+1));
    	for(int i=1,t=1;i<=n;i++){
    		if(t<i) t=i;
    		while(t<n&&s[t]==s[t+1]) t++;
    		same[i]=t;
    	}
    	for(int i=1;i<=n;i++) rank[i]=i;
    	sort(rank+1,rank+n+1,cmp);
    	for(int i=1;i<=n;i++) printf("%d ",rank[i]);
    }
    
  • 相关阅读:
    牌库读取的修复
    法术迸发(Spellburst)
    传染孢子的探索
    降低电脑功耗——降低笔记本风扇噪音
    Playfield 类方法的注释
    大陆争霸( 最短路变形)
    POJ 2406 Power String
    括号匹配
    HDU 1003 最大子段和
    6.19noip模拟赛总结
  • 原文地址:https://www.cnblogs.com/lizehon/p/10804366.html
Copyright © 2011-2022 走看看