题意:定义一个偶串为一个可写为一个字符串复制两次的字符串。S为一个偶串,定义f(S)为在S后加最少的字符(大于等于1个)使S成为的偶串。

设f(SS)=STST,g(S)=ST。则T为S最小的周期。
$$g(ST)=STT(|T| \\mid |S|) $$
$$g(ST)=STS(|T| \\nmid |S|)$$

#include <bits/stdc++.h>
using namespace std;
const int N=210000;
#define ll long long
char s[N];
ll L,R;
int nex[N];
ll len[210];
struct node
{
    ll a[26];
    void init(int x)
    {
        for(int i=1;i<=x;i++)
            a[s[i]-'a']++;
    }
    friend node operator + (const node &r1,const node &r2)
    {
        node ret;
        for(int i=0;i<26;i++)
            ret.a[i]=r1.a[i]+r2.a[i];
        return ret;
    }
    friend node operator - (const node &r1,const node &r2)
    {
        node ret;
        for(int i=0;i<26;i++)
            ret.a[i]=r1.a[i]-r2.a[i];
        return ret;
    }
    void print()
    {
        for(int i=0;i<26;i++)
            printf("%lld ",a[i]);
        puts("");
    }
}v[210];
node calc(ll x)
{
    int p;
    for(p=1;;p++)
        if(len[p]>=x)break;
    node ret,t;
    memset(&ret,0,sizeof(ret));
    memset(&t,0,sizeof(t));
    for(;p>=1;p--)
        if(len[p]<=x)
        {
            ret=ret+v[p];
            x-=len[p];
        }
    t.init(x);
    ret=ret+t;
    return ret;
}
int main()
{
    //freopen("tt.in","r",stdin);
    scanf("%s%lld%lld",s+1,&L,&R);
    len[2]=strlen(s+1)/2;
    nex[1]=0;
    for(int i=2,j=0;i<=len[2];i++)
    {
        while(j&&s[j+1]!=s[i])
            j=nex[j];
        if(s[j+1]==s[i])j++;
        nex[i]=j;
    }
    len[1]=len[2]-nex[len[2]];
    v[1].init(len[1]);
    v[2].init(len[2]);
    for(int i=3;;i++)
    {
        len[i]=len[i-1]+len[i-2];
        v[i]=v[i-1]+v[i-2];
        if(len[i]>=R)break;
    }
    (calc(R)-calc(L-1)).print();
    return 0;
}

标签: 字符串

添加新评论