链接:http://icpc.upc.edu.cn/running.php?cid=1828
题意:多组样例,每行给出一个字符串S,两个整数A,B。问一个字符串中出现次数在[A,B]范围内的子串的种类数。
思路:后缀自动机模板题。但是,题目说范围是2e6,数组开这么大会报运行错误,看到1e5就过了。oj问题。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define ll long long
#define llu unsigned ll
using namespace std;
const int maxn=1e5+10;
char str[maxn];
int x[maxn<<1],y[maxn<<1];
struct Sam
{
int last,cnt;
int nt[maxn<<1][26],len[maxn<<1];
int fa[maxn<<1],sum[maxn<<1];
void init(int n)
{
last=1;
cnt=1;
fa[1]=0;
len[1]=0;
for(int i=0;i<=n;i++)
{
fa[i]=0;
len[i]=0;
sum[i]=0;
memset(nt[i],0,sizeof(nt[i]));
}
}
void _insert(int c)
{
int nowp=++cnt,p=last;
len[nowp]=len[last]+1;
while(p&&!nt[p][c]) nt[p][c]=nowp,p=fa[p];
if(!p) fa[nowp]=1;
else
{
int q=nt[p][c];
if(len[q]==len[p]+1) fa[nowp]=q;
else
{
int nowq=++cnt;
len[nowq]=len[p]+1;
memcpy(nt[nowq],nt[q],sizeof(nt[q]));
fa[nowq]=fa[q];
fa[nowp]=fa[q]=nowq;
while(p&&nt[p][c]==q) nt[p][c]=nowq,p=fa[p];
}
}
last=nowp,sum[last]=1;
return ;
}
void _count(void)
{
memset(x,0,sizeof(x));
for(int i=1;i<=cnt;i++) x[len[i]]++;
for(int i=1;i<=cnt;i++) x[i]+=x[i-1];
for(int i=1;i<=cnt;i++) y[x[len[i]]--]=i;
for(int i=cnt;i>=1;i--) sum[fa[y[i]]]+=sum[y[i]];
return ;
}
void creat(void)
{
int len=strlen(str);
init((len+5)*2);
for(int i=0;i<len;i++)
_insert(str[i]-'A');
_count();
return ;
}
}sam;
int main(void)
{
int k1,k2;
while(~scanf("%s%d%d",str,&k1,&k2))
{
sam.creat();
ll ans=0;
for(int i=1;i<=sam.cnt;i++)
{
if(sam.sum[i]>=k1&&sam.sum[i]<=k2)
{
ans+=(sam.len[i]-sam.len[sam.fa[i]]);
}
}
printf("%lld\n",ans);
}
return 0;
}