給定乙個迴圈串,問從哪個位置剖分能使得字典序最小最小表示法裸題,字尾陣列裸題
然而字尾陣列我還不太會構造
所以轉而學習了一下最小表示法
樸素演算法:
將原陣列複製一遍
列舉兩個串的開頭p1
, p2
,依次比較兩個串的每一位
每當 s[p
1+k]
≠s[p
2+k]
時,字典序較大的頭指標向後移一位
時間複雜度 o(
n2)
最小表示法:
與樸素演算法大致相同
就是在發現 s[
p1+k
]≠s[
p2+k
] 時,字典序較大的頭指標向後移動 k位
證明如下:
不妨設 s[
p1+k
]>s[
p2+k
] ,則 ∀i
∈[p−
1,k)
都不可能成為最小串的頭
因為如果其為最小串的頭,那麼可以在第二個串中對應找乙個位置
使得 si1
,i1+
k>si
2,i2
+k所以 ∀i∈
[p−1
,k) 都不可能成為最小串的頭
同理 s[p
1+k]
p2+k
],∀i
∈[p−
2,k)
都不可能成為最小串的頭
所以在發生失配時,頭指標直接向後移動k+
1 位s[
p1+k
]=s[
p2+k
] ,則 k就自增,不斷比較,直到失配
或者當k==n
時,此時就得到了最小串 p1
≠p2 不妨設 p2
>p1
由 1和 2可知,p1
−>p2
的字元都不可能是最小串的開頭
由於 s1==
s2,所以相同結論可以對映到 s2
上 所以就可得出 p1
即最小串的開頭
最後 p
1 ,p2
中較小的那個就是最小串的頭指標
如果 p
1 ,p2
都小於n,最小串不唯一,任意乙個都行
如果最小串唯一,那麼有乙個勢必滑動出 n了,所以取最小的
顯然尾指標最多移動 4*n次,所以演算法時間複雜度 o(
n)
#pragma comment(linker, "/stack:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
typedef pair pii;
typedef
long
long ll;
typedef
unsigned
long
long ull;
typedef
double dbl;
typedef
long
double ldbl;
#define mst(a,b) memset(a,b,sizeof(a))
#define clr(a) mst(a,0)
#define sqr(a) (a*a)
const
int maxn=3e5+10;
int n;
int inpt[2*maxn];
int main()
int p1=0,p2=1;
while(p1int len=0;
while(inpt[p1+len]==inpt[p2+len]&&lenif(len==n) break;
if(inpt[p1+len]>inpt[p2+len]) p1+=len+1;
else p2+=len+1;
if(p1==p2) p2++;
}int ansp=min(p1, p2);
for(int i=ansp; iprintf("%d ", inpt[i]);
puts("");
}return
0;}
SCU 1118 上車人數
問題描述 公共汽車從始發站 稱為第1站 開出,在始發站上車的人數為a,然後到達第2站,在第2站有人上 下車,但上 下車的人數相同,因此在第2站開出時 即在到達第3站之前 車上的人數保持為a人。從第3站起 包括第3站 上 下車的人數有一定的規律 上車的人數都是前兩站上車人數之和,而下車人數等於上一站上...
BZOJ4504 主席樹 K個串
只區間出現一次的數就是上一次出現在位置在區間外的數,這個可以用主席樹實現,然後套用超級鋼琴的思想就可以了。include include include include include using namespace std const int n 100010 typedef long long ...
2023年SCU校賽總結
這是某個我不認識的人在討論裡面催我做總結的,最近太忙啦,畫個圈圈詛咒你,哼 第二次打川大校賽呀,去年就被江安校區那條大江震撼了,然後今年帶學弟學妹他們去看他們反而看了一會就抄小路走了,然後找到了比賽地點,然後樓裡面一堆電科大佬的說,我還是沒有去找秦隊長面基,差距太大了啊,然後本來打算吃飯的,然後學弟...