Luogu P1368 【模板】最小表示法
阿新 • • 發佈:2020-11-27
https://www.luogu.com.cn/problem/P1368
題面
給定一個字串,求出最小的迴圈表示
分析
先擴充套件兩倍
給定兩個起點\(i,j\),找到第一個\(a[i+k]!=a[j+k]\),判斷大小
不妨假設\(a[i+k]>a[j+k]\)
則對於起點\(a\in [i,i+k]\)總會比起點\(b\in [j,j+k]\)劣
\(\therefore i=i+k+1\)
因為\((i,j)\)只加,所以均攤\(O(n)\)
#include<bits/stdc++.h> using namespace std; const int N=6e5+5; int n,a[N]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]),a[i+n]=a[i]; } int i=1,j=2; while(i<=n&&j<=n) { int k; for(k=0;k<=n&&a[i+k]==a[j+k];k++); if(k==n) { for(int l=1;l<=n;l++) { printf("%d ",a[l]); } return 0; } if(a[i+k]>a[j+k]) i+=k+1; else j+=k+1; if(i==j) j++; } if(i>n) { for(int k=j;k<=n;k++) printf("%d ",a[k]); for(int k=1;k<j;k++) printf("%d ",a[k]); } else { for(int k=i;k<=n;k++) printf("%d ",a[k]); for(int k=1;k<i;k++) printf("%d ",a[k]); } return 0; }