考慮第一次切割,必然切割的是翻轉後字典序最小的字首,偽證:
若切割位置更靠前:則會導致第乙個數翻轉後更靠前,字典序必然更大。
若切割位置更靠後,則顯然也會導致字典序更大。
↑,sa即可
對於第二次切割,有結論:將序列分割成兩段再分別翻轉得到的序列,可以看作是將兩個原序列拼接得到的新序列中的某個字串翻轉得到的序列。
因此計算新序列的sa,再從中選取字典序最小的合適的字尾即可。
因為要基數排序而又沒有告訴權值的範圍,因此要離散化。
#include#include#includeusing namespace std;#define n 400001
struct pointt[n];
bool operator < (point a,point b)
void build_sa(int s,int range,int n)
}int main()
}int n2=n-p1;
reverse_copy(s+p1,s+n,rev);
memcpy(rev+n2,rev,sizeof(int)*n2);
build_sa(rev,zy,n2<<1);
for(int i=0;i<(n2<<1);++i)
if(sa[i]&&sa[i]return 0;
}
POJ3581 Sequence 字尾陣列)
大致題意 給出n個數,把這個數列分為三段,再把三段反轉後連線在一起成為乙個新串,求字典序最小的新串。大致思路 由於需要翻轉,所以在輸入時就按照反序輸入。比如樣例輸入是5 10 1 2 3 4。我們從後向前讀入就變為5 4 3 2 1 10。對這列數求出字尾陣列。在大於2的後最中找到最小的字尾並輸出。...
POJ3581 Sequence(字尾陣列)
題意 給乙個串,串的第乙個字元比後面的都大,要把它分成三段,然後反轉每一段,求能得到的字典序最小的串是什麼。首先,第一段是可以確定的 把原串反轉,因為第乙個字元是最大的,它是唯一的,不存在反轉串的字尾之間有包含關係,所以取最小的字尾這就是第一段的字串 然後後面兩段,如果確定分割位置可以發現這兩段字串...
POJ 3581 Sequence(字尾陣列)題解
已知某字串 str 滿足 str 1 max 現要求把這個字串分成連續的三組,然後每組都翻轉,問字典序最小是什麼?因為 str 1 max 所以第一部分直接翻轉後跑 sa 求字典序最小就行了。那麼現在問題轉化為 把這個字串分成兩半,然後每組都翻轉,問字典序最小是什麼?我們假設這個字串為 s 1s 2...