[SNOI2019] 字符串 - 思维
作者:互联网
Description
给定一个长度为 \(n \le 10^6\) 的字符串,设删掉第 \(i\) 个字符后得到的字符串为 \(s_i\),按照字典序对 \(s_1,s_2,...,s_n\) 排序。如果两个字符串相等,那么认为编号小的字符串字典序更小。
Solution
对于原串 \(a\),预处理出对于每一个 \(i\),最小的 \(j>i\) 使得 \(a_i \neq 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");
}
标签:思维,int,long,--,字符串,------,SNOI2019,id 来源: https://www.cnblogs.com/mollnn/p/13752785.html