基數排序
怎麼說呢,其實這已經是上學期DS&A學過的了,但是當時沒怎麼看,以爲std::sort()天下第一,其他排序算法都沒啥用武之地,直到昨天看到了這道題:
題意很簡單,個長度爲的字符串,輸出按字典序排序後的結果,其中。
第一反應:這不是字典樹sb題嗎?
剛打開模板,突然發現不太對勁,,這誰頂得住啊…
既然空間上不行,就要換一個可行的算法了。
看到數據,,盲猜正解應該是的算法,最多加個,但有什麼算法是和字符串長度有關的呢?
長度…排序…對了,好像上學期學過一個排序算法…基數排序!
那麼什麼是基數排序呢,我先去菜鳥教程偷個圖:
簡而言之,基數排序利用了數據不同位置的不同權重對順序的影響(比如,對於字符串,的大小對不同的字符串順序並無影響)來保證對每趟排序後的數據局部有序,全部排序後的數據整體有序。
對於這道題,只需要把上面gif的0~9改爲a~z,然後對於每一個字符串從後往前排趟序就好了,時空複雜度。
AC代碼:
有一說一,5e6個字符用cin竟然沒TLE
#include <bits/stdc++.h>
#define N 5000010
using namespace std;
int n,order[N];//order爲排序後字符串的下標
queue<int> q[26];//表示26個字母作爲基數
string s[N];
void redix_sort(int a[],int len,int n)//基數排序O(nlen)
{
for(int k=len-1;~k;k--)
{
for(int i=1;i<=n;i++)
q[s[a[i]][k]-'a'].push(a[i]);
for(int i=0,j=0;j<26;j++)
while(q[j].size())
{
a[++i]=q[j].front();
q[j].pop();
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
order[i]=i;//字符串初始順序
}
redix_sort(order,s[1].size(),n);//對order而不是s排序避免了字符串複製的時間
for(int i=1;i<=n;i++)
cout<<s[order[i]]<<"\n";
}
今天比較短,畢竟有課要早點睡x
2020.3.30 4:28 a.m.
21:24 updated:試了一遍,直接sort()竟然過了,果然是我太菜了。