• [SNOI2019]字符串


    题面

    luogu

    题解

    考虑对于后缀(s_i,s_j)怎么比较两个的大小,这里钦定(i<j)
    (i)把图一画显然有([1,i-1])是相同的一段,([j+1,n])是相同的一段。
    那么只需要判断中间的大小关系。
    你把中间的和后面的合并,发现是(i)(i+1)的后缀的大小关系在([i,j])这一段内的体现。
    这个时候直接求(lcp)然后讨论一下即可。

    代码实现

    /*
      mail: mleautomaton@foxmail.com
      author: MLEAutoMaton
      This Code is made by MLEAutoMaton
    */
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define ll long long
    #define REP(a,b,c) for(int a=b;a<=c;a++)
    #define re register
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    inline int gi(){
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=1000010;
    int n,lcp[N],p[N];
    char s[N];
    bool cmp(int a,int b){
    	int big=1;
    	if(a>b)swap(a,b),big^=1;
    	if(lcp[a+1]>=b-a)return big;
    	return big^(s[a+lcp[a+1]+1]>s[a+lcp[a+1]]);
    }
    int main(){
    	n=gi();scanf("%s",s+1);
    	for(int i=1;i<=n;i++){
    		lcp[i]=max(0,lcp[i-1]-1);
    		while(s[i+lcp[i]]==s[i-1+lcp[i]])lcp[i]++;
    	}
    	for(int i=1;i<=n;i++)p[i]=i;
    	sort(p+1,p+n+1,cmp);
    	for(int i=1;i<=n;i++)printf("%d%c",p[i],i==n?'
    ':' ');
    	return 0;
    }
    
  • 相关阅读:
    hdu 5902 Seam Carving
    hdu 5091 Beam Cannon
    hdu 1542 Atlantis
    hdu 2196 Computer
    第一个爬虫和测试
    排球比赛规则
    第十周博客作业
    科学计算可视化
    用matplotlib绘制图像
    面对对象学习
  • 原文地址:https://www.cnblogs.com/fexuile/p/11624217.html
Copyright © 2020-2023  润新知