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;
}

猜你喜欢

转载自www.cnblogs.com/Yokel062/p/13399571.html