webhooks鉤子自動部署程式碼簡介
阿新 • • 發佈:2020-11-18
目錄
,顯然,
模板題
很疑惑怎麼就是藍題了,這演算法不難理解呀(比KMP好多了)
概念
給定一個字串s,不斷把s的最後一個元素放到開頭,可以得到n個字串,其中字典序最小的一個稱為s的最小表示.
另外,這n個字串被稱作是迴圈同構的,為了方便敘述,這裡定義b[]
儲存s的迴圈同構字串,且b[i]
表示以s的第i位開頭的字串
樸素演算法
根據定義,列舉所有的b,逐位匹配找出最小值,複雜度O(n^2)
優化演算法
首先,將s變化為:s=s+s
,得b[i]=s.substr(i,s.size())
(substr
意義同C++string)
若s[i+k] > s[j+k]
b[i]
不是最小表示.此外,b[i+1],b[i+2]...b[i+k]
均不是最小表示
原因:
對於p(1<=p<=k),存在一個比b[i+p]
更小的迴圈同構串:b[j+p]
(這裡不太好理解,但是仔細想想,或者搞個字串模擬一下,還是可以理解的)
因此,每次找到s[i+k] > s[j+k]
時,i=i+k+1
,若得到的i等於j,則++i
時間複雜度
結論:O(n)
證:
若每次比較從前向後掃描了k的長度,則i或j二者之一會向後移動k,而i和j合計一共最多向後移動2n的長度,因此時間複雜度為O(n)
模板題程式碼
#include <iostream> #include <cstdio> using namespace std; int read() { int re = 0; bool sig = false; char c = getchar(); while(c < '0' || c > '9') { if(c == '-')sig = true; c = getchar(); } while(c >= '0' && c <= '9') re = (re << 1) + (re << 3) + c - '0', c = getchar(); return sig ? -re : re; } int n ; int a[600010]; int main() { n = read(); for(int i = 1 ; i <= n ; i++) a[i] = a[n + i] = read(); int i = 1 , j = 2 , k; while(i <= n && j <= n) { for(k = 0 ; k < n && a[i + k] == a[j + k] ; k++); if(k == n)break; if(a[i + k] > a[j + k]) { i = i + k + 1; if(i == j)++i; } else { j = j + k + 1; if(i == j)++j; } } int ans = (i < j ? i : j); for(int p = ans ; p < ans + n ; p++) printf("%d " , a[p]); return 0; }