HDU 6761 Minimum Index(Lyndon+前缀的最小后缀)
题意:求字符串的每个前缀的最小后缀。
题解:最小的后缀一定是最后一个Lyndon串,Lyndon分解。
#include <bits/stdc++.h> #define IO_read ios::sync_with_stdio(false);cin.tie(0) #define fre freopen("in.txt", "r", stdin) #define _for(i,a,b) for(int i=a; i< b; i++) #define _rep(i,a,b) for(int i=a; i<=b; i++) #define inf 0x3f3f3f3f #define lowbit(a) ((a)&-(a)) using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0'; if(op) x=-x; } template <class T> void write(T x) { if(x<0) putchar('-'), x=-x; if(x>=10) write(x/10); putchar('0'+x%10); } const int maxn=1e6+5; char s[maxn]; int T, n; ll pos[maxn]; ll f[maxn], base=1112, mod=1e9+7; void lyndon() { for(int i=1; i<=n; ) { int j=i, k=i+1; pos[i]=i; while(k<=n && s[j]<=s[k]) { if(i==j) pos[k-1]=i; else pos[k-1]=pos[j-1]+k-j; if(s[j]<s[k]) j=i; else j++; k++; } while(i<=j) { pos[i+k-j-1]=i; i+=k-j; } } } int main() { fre; f[1]=1; for(int i=2; i<=maxn; i++) f[i]=f[i-1]*base%mod; read(T); while(T--) { scanf("%s", s+1); n=strlen(s+1); lyndon(); ll ans=0; for(int i=1; i<=n; i++) ans=(f[i]*pos[i]+ans)%mod; printf("%lld\n", ans); } return 0; }