Minimum Index【】-2020杭電多校1
阿新 • • 發佈:2020-07-31
題目連結:
http://acm.hdu.edu.cn/showproblem.php?pid=6761
分析:
\(Lyndon\) 分解:
\(Lyndon\) 串:對於字串 \(s\),如果 \(s\) 的字典序嚴格小於 \(s\) 的所有後綴的字典序,我們稱 \(s\) 是簡單串,或者 \(Lyndon\) 串 。
性質:任意字串 \(s\) 都可以分解為 \(s=s_1s_2…s_k\),其中 \(∀s_i\) 為 \(Lyndon\) 串且 \(s_i⩾s_{i+1}\),且這種分解方法是唯一的。
\(Duval\) 演算法:
該演算法可以在 \(O(n)\) 的時間內求出串 \(s\)
模板程式碼-Lyndon 分解:
#include<bits/stdc++.h> using namespace std; const int MAXN = (1 << 21) + 1; char s[MAXN]; int main() { scanf("%s", s + 1); int N = strlen(s + 1), j, k; for(int i = 1; i <= N;) { j = i; k = i + 1; while(k <= N && s[j] <= s[k]) { if(s[j] < s[k]) j = i; else j++; k++; } while(i <= j) { printf("%d ", i + k - j - 1); i += k - j; } } return 0; }
程式碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+6; const int mod=1e9+7; int ans[N]; char ss[N]; int main() { int t; scanf("%d",&t); while(t--) { scanf("%s",ss+1); int len=strlen(ss+1); int i=1; ans[1]=1; while(i<=len) {//重新開始分解 int j=i,k=i+1;//i是近似串的開始 while(k<=len&&ss[j]<=ss[k]) { if(ss[j]<ss[k])//加入到近似的Lyndon串中 { j=i; ans[k]=i; } else//繼續保持 { ans[k]=ans[j]+k-j; j++; } k++; } while(i<=j)//起點向後移 i+=k-j; ans[k]=i;// } ll base=1112,fac=1,res=0; for(int i=1;i<=len;i++) { res=(res+fac*ans[i]%mod)%mod; fac=fac*base%mod; } printf("%lld\n",res); } return 0; }
參考部落格:
https://oi-wiki.org/string/lyndon/
https://www.cnblogs.com/zwfymqz/p/10198690.html
https://www.cnblogs.com/st1vdy/p/13362219.html