结论题,假设那个串叫SS,并且操作一次后变成TT。
首先自己画画就会发现T比S多出来的那一段一定是S的一个周期。(注意S的周期和SS的周期不是一回事,比如样例)
前缀技能:如果a和b都是s的周期,那么(a, b)也是s的周期。因此s的最小正周期是s的任何一个周期的周期,证明类似辗转相除。
然后我们证明对于任意情况下,你选择的周期,记做g,越小越好,也就是选择最小周期g。否则,假设选择的是h是S的一个周期并且做出来的结果比g好。那么根据一些border的知识我们知道因为g是最小正周期所以h的长度是g的长度我的若干倍,那么显然h能做到的事情g也能做到。因此h不会比g好。
否则,我们证明这么两件事情:
1)f(SS)=SgSg
这个其实自己画画就能画出来。
2)若S的最小正周期是g,那么串Sg的最小正周期为:
a)g,如果g的长度是S的因数,这显然。
b)S,else。我们证明b)。
反证。首先S是Sg的一个周期。因此假定h是Sg的最小正周期,那么|h|< |S|,否则结论成立。那么根据border的知识,S的h的倍数。因此h也是S的一个周期,从因此g的长度是h的长度的因数,因此g的长度是S的长度的因数,这样就gg了。
我们考虑上述两个结论在干啥,根据1),我们知道就是,考虑这个偶串的前半段会不停的加上一个最小正周期。
如果g的长度是S的长度的因数,那么相当与每次在后面加入两个g,也就是最终序列全是g,自己特判掉就可以了。下文假设g的长度不是S的长度的因数
根据后半段,我们假设操作了x次后这个串的前半部分是Sg,S是操作第x-1次串,那么S是Sg的最小正周期,第x+1次操作后的串前半部分就是SgS,也就是每次操作得到的串都是上两次操作得到的串拼起来,就像一个斐数一样。
实现的时候其实不用特判整除的情况。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 200010
#define lint long long
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
char s[N];int nxt[N];
struct E{
lint len,cnt[26];E() { len=0,memset(cnt,0,sizeof cnt); }
inline E operator=(const E &e)
{ return len=e.len,memcpy(cnt,e.cnt,sizeof cnt),*this; }
inline E operator+(const E &e)const
{
E res;res=*this;
for(int i=0;i<26;i++) res.cnt[i]+=e.cnt[i];
return res.len+=e.len,res;
}
inline E operator-(const E &e)const
{
E res;res=*this;
for(int i=0;i<26;i++) res.cnt[i]-=e.cnt[i];
return res.len-=e.len,res;
}
inline E operator+=(const E &e) { return (*this)=(*this)+e; }
}a[1010];
inline int getg(char *s,int n)
{
for(int i=2;i<=n;i++)
{
int &j=nxt[i];j=nxt[i-1];
while(j&&s[j+1]!=s[i]) j=nxt[j];
if(s[j+1]==s[i]) j++;
}
return n-nxt[n];
}
inline E query(lint n,int c)
{
E ans;
for(int i=c;i>=1;i--)
if(n>=a[i].len) n-=a[i].len,ans+=a[i];
for(int i=1;i<=n;i++) ans.cnt[s[i]-'a']++;
return ans;
}
int main()
{
scanf("%s",s+1);int n=(int)strlen(s+1),c=2;
int k=n/2,g=getg(s,k);lint l,r;cin>>l>>r;
for(int i=1;i<=k;i++) a[1].cnt[s[i]-'a']++;
a[2]=a[1],a[1].len=k,a[2].len=k+g;
for(int i=1;i<=g;i++) a[2].cnt[s[i]-'a']++;
while(a[c-1].len+a[c].len<=r) c++,a[c]=a[c-1]+a[c-2];
E ans=query(r,c);
ans=ans-query(l-1,c);
for(int i=0;i<26;i++) printf("%lld ",ans.cnt[i]);
return !printf("\n");
}