題意:給乙個串,串的第乙個字元比後面的都大,要把它分成三段,然後反轉每一段,求能得到的字典序最小的串是什麼。
首先,第一段是可以確定的:把原串反轉,因為第乙個字元是最大的,它是唯一的,不存在反轉串的字尾之間有包含關係,所以取最小的字尾這就是第一段的字串;
然後後面兩段,如果確定分割位置可以發現這兩段字串構成是乙個從分割位置出發逆時針迴圈回來的串——
即接下來要求的就是剩餘部分的反轉的最小表示,可以用字尾陣列來做:把串加長一倍,答案就在最小的且長度大於等於原串長度的字尾了。
注意,分的段要非空。。所以還要在第一段、後面兩段的分割加些判斷。
這題好難a,不知道為什麼。。wa來wa去。。改啊改,終於re來re去。。跟著別人把數字離散化後才ac了。。
1 #include2 #include3 #include4 #include5using
namespace
std;
6#define maxn 222222
7int
wa[maxn],wb[maxn],wv[maxn],ws[maxn];
8int cmp(int *r,int a,int b,int
l)11
intsa[maxn];
12void sa(int *r,int n,int
m)33}34
35int
a[maxn],r[maxn];
36int
b[maxn],bn;
37int
main()
44 sort(b,b+n);
45 bn=unique(b,b+n)-b;
46for(int i=0; ii)
49for(int i=0; ii)
52 r[n]=0
;53 sa(r,n+1,bn+1
);54
int m=0;55
for(int i=1; i<=n; ++i)
60 n=sa[i];
61for(int j=0; jj)
65 r[m]=0;66
break;67
}68}69 sa(r,m+1,bn+1
);70
for(int i=1; i<=m; ++i)75}
76return0;
77 }
POJ3581 Sequence 字尾陣列)
大致題意 給出n個數,把這個數列分為三段,再把三段反轉後連線在一起成為乙個新串,求字典序最小的新串。大致思路 由於需要翻轉,所以在輸入時就按照反序輸入。比如樣例輸入是5 10 1 2 3 4。我們從後向前讀入就變為5 4 3 2 1 10。對這列數求出字尾陣列。在大於2的後最中找到最小的字尾並輸出。...
字尾陣列 poj3581 Sequence
考慮第一次切割,必然切割的是翻轉後字典序最小的字首,偽證 若切割位置更靠前 則會導致第乙個數翻轉後更靠前,字典序必然更大。若切割位置更靠後,則顯然也會導致字典序更大。sa即可 對於第二次切割,有結論 將序列分割成兩段再分別翻轉得到的序列,可以看作是將兩個原序列拼接得到的新序列中的某個字串翻轉得到的序...
POJ3581 Sequence 字尾樹組
題意 n個數字組成的序列,第乙個數字最大,把序列分成3部分,每個部分分別翻轉,輸出翻轉後字典序最小的序列。字尾陣列變一下,先求出 第乙個分割的位置,然後再求一次字尾陣列,求出第二個位置。輸出就好了。此題要採用單組輸入。1 include 2 include 3 include 4 include 5...