这里写代码片
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string ‘ababa’ F(3) will be 2 because there is a string ‘aba’ that occurs twice. Your task is to output F(i) for every i so that 1<=i<=|S|.
Input
String S consists of at most 250000 lowercase latin letters.
Output
Output |S| lines. On the i-th line output F(i).
Example
Input:
ababa
Output:
3
2
2
1
1
题意:给出一个字符串,问每个长度最多有多少个相同的子串。
做法:对于每一个字母st[i] = x,以它结尾的子串可以用s0s1,,si所在的节点和这个节点的所有祖先表示,每个祖先可以表示以它结尾的mr到ml这一段,那么如果给每个这样的节点赋值为1,那么每一个节点代表的字符串出现的次数就是他所有儿子的1的和,现在插入的时候把这样的节点赋值为1,在插入结束的是用拓扑序统计每个节点出现的次数,因为每个节点代表的是一段区间,那么可以用线段树区间更新维护这个东西,但是我在用线段树时,每次查询i到i的值,结果T了,然后我把查询改成了递归就a了,,,
还有一个更好的做法,就是对于每个节点,只更新它的mx值,然后对于d[i] = max(d[i],d[i+1])就可以得到每个长度最大的值了,
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int N = 3e5+7;
char st[N];
int sum[N<<2],lz[N<<2];
void pushdown(int rt){
if(lz[rt]){
sum[rt<<1] = max(sum[rt<<1],lz[rt]);
sum[rt<<1|1] = max(sum[rt<<1|1],lz[rt]);
lz[rt<<1] = max(lz[rt<<1],lz[rt]);
lz[rt<<1|1] = max(lz[rt<<1|1],lz[rt]);
lz[rt] = 0;
}
}
void update(int L,int R,int c,int l,int r,int rt){
if(L <= l && R >= r){
sum[rt] = max(sum[rt],c);
lz[rt] = max(lz[rt],c);
return ;
}
pushdown(rt);
int mid = l+r>>1;
if(mid >= L) update(L,R,c,l,mid,rt<<1);
if(mid < R) update(L,R,c,mid+1,r,rt<<1|1);
sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
}
int query(int L,int R,int l,int r,int rt){
if(L <= l && R>= r) return sum[rt];
pushdown(rt);
int mid = l+r>>1;
int ans = 0;
if(mid >= L) ans = query(L,R,l,mid,rt<<1);
if(mid < R) ans = max(ans,query(L,R,mid+1,r,rt<<1|1));
return ans;
}
struct SAM{
int pre[N*2],nex[N*2][26],mx[N*2],cnt[N*2],top,last;
int son[N*2];
void init(){
top = 2;
last = 1;
memset(nex[1],0,sizeof(nex[1]));
}
int newnode(int x){
memset(nex[top],0,sizeof(nex[top]));
mx[top] = x;
return top++;
}
void add(int x){
int p = last;
int np = newnode(mx[p]+1);
while(p && nex[p][x] == 0) nex[p][x] = np,p = pre[p];
if(p == 0){
pre[np] = 1;
}
else{
int q = nex[p][x];
if(mx[q] == mx[p]+1){
pre[np] = q;
}
else{
int nq = newnode(mx[p]+1);
for(int i = 0;i < 26;i ++) nex[nq][i] = nex[q][i];
pre[nq] = pre[q];
pre[np] = pre[q] = nq;
son[nq]++;
while(p && nex[p][x] == q) {
nex[p][x] = nq;
p = pre[p];
}
}
}
//cout << x << ' '<< pre[np] << ' '<< np << endl;
son[pre[np]]++;
last = np;
cnt[np] = 1;
}
void solve(){
queue<int> que;
for(int i = 2;i < top;i ++)if(son[i] == 0) que.push(i);
while(!que.empty()){
int nx = que.front();
que.pop();
if(pre[nx] == 0)continue;
son[pre[nx]]--;
//cout << nx << ' '<< pre[nx] <<' '<< cnt[nx] <<endl;
cnt[pre[nx]] += cnt[nx];
if(son[pre[nx]] == 0) que.push(pre[nx]);
}
}
}sa;
int main(){
scanf("%s",st);
int len =strlen(st);
sa.init();
for(int i = 0;i < len;i ++) {sa.add(st[i]-'a');}
sa.solve();
for(int i = 2;i < sa.top;i ++){
int nl = sa.mx[sa.pre[i]]+1;
int nr = sa.mx[i];
if(nl < 1 || nr > len || nl > nr) continue;
update(nl,nr,sa.cnt[i],1,len,1);
}
for(int i = 1;i <= len;i ++){
printf("%d\n",query(i,i,1,len,1));
}
return 0;
}