2020杭電多校第一場 1011-Minimum Index lyndon分解+kmp
阿新 • • 發佈:2020-07-26
1011-Minimum Index
題意
給你一個字串\(s\),問字串\(s\)的每個字首的字典序最小的字尾是哪個,設每個字首的最小字尾的下標分別為\(t_1,t_2,\dots,t_n\),計算\(\sum_{i=1}^{n}t_i\times 1112^{i-1}\)。
分析
先做一遍lyndon分解,lyndon串的字典序嚴格小於它的所有後綴的字典序,且分解出的串\(w_1,w_2,\dots,w_n\)的字典序是非嚴格單調遞減的,對分解出的每個lyndon串分別處理:
設這個lyndon串為\(t\),對於它的一個字首\(t_i\),如果存在一個最小的\(j\),使得\(t[1\sim j]=t[i-j+1\sim i]\)
Code
#include<algorithm> #include<iostream> #include<cstring> #include<iomanip> #include<sstream> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define rep(i,x,n) for(int i=x;i<=n;i++) #define per(i,n,x) for(int i=n;i>=x;i--) #define sz(a) int(a.size()) #define rson mid+1,r,p<<1|1 #define pii pair<int,int> #define lson l,mid,p<<1 #define ll long long #define pb push_back #define mp make_pair #define se second #define fi first using namespace std; const double eps=1e-8; const int mod=1e9+7; const int N=1e6+10; const int inf=1e9; vector<string>v; void duval(string const& s) { int n = s.size(), i = 0; while (i < n) { int j = i + 1, k = i; while (j < n && s[k] <= s[j]) { if (s[k] < s[j]) k = i; else k++; j++; } while (i <= k) { v.push_back(s.substr(i, j - k)); i += j - k; } } } int T; string s; int nex[N],dp[N]; void get(string const &s){ int n=s.size(); nex[0]=-1; rep(i,0,n-1) dp[i]=i; for(int i=1,j=-1;i<n;i++){ while(~j&&s[j+1]!=s[i]) j=nex[j]; if(s[j+1]==s[i]) ++j; nex[i]=j; if(~j) dp[i]=min(dp[i],dp[j]); } } int main(){ ios::sync_with_stdio(false); //freopen("in","r",stdin); cin>>T; while(T--){ v.clear(); cin>>s; duval(s); int l=1; ll ret=1; ll ans=0; for(string x:v){ get(x); rep(i,0,sz(x)-1){ ans=(ans+1ll*(l-dp[i])*ret%mod)%mod; ++l; ret=ret*1112%mod; } } printf("%lld\n",ans); } return 0; }