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

    Description

    给定一个长度为 (n le 10^6) 的字符串,设删掉第 (i) 个字符后得到的字符串为 (s_i),按照字典序对 (s_1,s_2,...,s_n) 排序。如果两个字符串相等,那么认为编号小的字符串字典序更小。

    Solution

    对于原串 (a),预处理出对于每一个 (i),最小的 (j>i) 使得 (a_i eq a_j)

    对于 (i<j) 的两个串,如果离 (a_i) 最近的不同的数是 (a_k)

    如果 (j<k),则证明编号为 (i,j) 的两个串完全相同,因此 (i) 排在 (j) 前面。

    如果 (j ge k),观察下面的示意图,可以发现,此时 (i) 排在 (j) 前面当且仅当 (a_k < a_i)

    ------x--
    ------x--
      i    j
    -----x--
    ------x-
    

    至于如何预处理出每个 (i) 对应的 (k),我们只需要倒序暴力递推即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    char a[N];
    int f[N],id[N],n;
    
    bool cmp(int i,int j)
    {
        if(i>j) 
        {
            swap(i,j);
            int k=f[i];
            if(j<k) return 0;
            if(a[k]<a[i]) return 0;
            return 1;
        }
        else
        {
            int k=f[i];
            if(j<k) return 1;
            if(a[k]<a[i]) return 1;
            return 0;
        }
        
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>a+1;
        
        for(int i=1;i<=n;i++) id[i]=i;
        
        f[n+1]=n+1;
        for(int i=n;i>=1;--i)
        {
            if(a[i]!=a[i+1]) f[i]=i+1;
            else f[i]=f[i+1];
        }
    
        sort(id+1,id+n+1,cmp);
        for(int i=1;i<=n;i++) 
        {
            cout<<id[i]<<" ";
        }
    
        //system("pause");
    }
    
    
  • 相关阅读:
    VMware Workstation网卡不启动
    解决IE10以下对象不支持“bind”属性或方法
    二分法查找
    选择排序与冒泡排序
    方法内部开启线程的方法
    重写Collections实现自定义排序
    根据反射生成SQL语句
    vue插件安装备忘
    vue cli4.x 新建项目 过程提醒
    php setcooike()失败的原因之一,希望能帮到你
  • 原文地址:https://www.cnblogs.com/mollnn/p/13752785.html
Copyright © 2011-2022 走看看