時間限制:
2000
ms | 記憶體限制:
65535
kb 難度:
描述 給出乙個長為len的字串str,把字串的首尾相連,然後以每個字元為起點,順時針遍歷每個字元,得到len個新的字串,然後把這len個字串按照字典序從小到大的順序進行排序,取出排完序後的每個字串的最後乙個字元,形成乙個新的字串s。求s。
如下圖。假設str=「topcoder」,則得到的新的字串有
topcoder, opcodert, pcoderto, codertop, odertopc, dertopco, ertopcod, rtopcode,
按字典序排完序為
codertop, dertopco, ertopcod, odertopc, opcodert, pcoderto, rtopcode, topcoder,
則取出每個字串最後乙個字元之後形成的字串為podctoer,即s = 「podctoer」。
輸入多組測試資料。
每組測試資料報括乙個字串,長度不超過100000。字串由所有可列印字元組成。
輸出每組資料佔一行,輸出s。
樣例輸入
topcoder樣例輸出i love you
podctoerievu yloo
解:以topcoder為例
首先先翻倍topcodertopcoder,那麼我們實際上是要找長度為len的子串的字典序排序結果,至於是在前半區還是後半區,加乙個判斷即可。
現在是如何解決長度為len,解決方法就是不管它。。。舉個例子
兩個長度為len的子串1,子串2,它的實際字尾組成長子串1,長子串2,那麼有以下3種情況
1、子串1 > 子串2,那麼顯然長子串1 > 長子串2
2、子串1 < 子串2,那麼顯然長子串1 < 長子串2
3、子串1 = 子串2 ,那麼長子串1與長子串2的結果不確定
綜上,如果我們直接對所有長子串進行字典序排序的話,對應的子串的字典序排序結果也是正確的,只是不穩定,然而不穩定對本題的結果並沒有影響。。求字典序的工作就交給字尾陣列的sa啦
下面附上c++的**:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2147483647
#define linf 9223372036854775807ll
#define ll long long
using namespace std;
const int maxn = 200010;
void da(int str, int sa, int rank, int n, int m);
int t1[maxn], t2[maxn], c[maxn];
int dstr[maxn], sa[maxn], rank[maxn];
char str[maxn],ans[maxn];
int main()
ans[len] = '\0';
printf("%s\n", ans); }
return 0; }
bool cmp(int *r, int a, int b, int l)
void da(int str, int sa, int rank, int n, int m)
int k = 0;
n--;
for (i = 0; i <= n; i++) rank[sa[i]] = i;
return; }
字串 字串排序
頻率統計 將頻率轉換為索引 資料分類 回寫頻率統計 統計每個字元出現的次數 將頻率轉換為索引 確定不同字元首位置 從右到左檢查檢查鍵中的字元 public class lsd public class msd public static void sort string a private stat...
《演算法》 字串 字串排序
輸入字串和字串對應的組別 組別也是字串的鍵 在滿足組別有小到大排序的情況下,將字串按字母順序排序 第一步,記錄組別的頻率 為了得到某個字串在排序後的範圍,比如組別2肯定在組別1後面,在組別3前面,把每個組別有多少個人記錄下來,方便我們定位 第三步,分類 該組別的位置起點 向後挪一位 因為當前位被用了...
字串排序
從鍵盤輸入10個學生的姓名和成績,請按字典序排列學生的姓名並輸出 姓名和成績對應關係保持不變 輸入共11行,前10行每行是乙個學生的姓名,最後一行是10個用空格分開的整數表示對應的10個學生成績。輸出姓名按字典序排列後的學生姓名和成績,共10行,每個學生的姓名和成績佔一行,姓名和成績間用逗號分開。b...