华丽的网站模板,wordpress文章页个性化定制,国外上市公司网站建设,wdcp设置网站安全解析
好题。 首先#xff0c;我们每次都令 sis_isi 是 si1s_{i1}si1 的后缀#xff0c;肯定是不劣的 问题就可以转化到 fail 树上了 首先肯定要线段树合并处理出endpos集合 朴素想法#xff1a;设父亲 fafafa 的结束位置为 posfapos_{fa}posfa#xff0c;若 [posfa−…解析
好题。 首先我们每次都令 sis_isi 是 si1s_{i1}si1 的后缀肯定是不劣的 问题就可以转化到 fail 树上了 首先肯定要线段树合并处理出endpos集合 朴素想法设父亲 fafafa 的结束位置为 posfapos_{fa}posfa若 [posfa−lenfa1,posfa][pos_{fa}-len_{fa}1,pos_{fa}][posfa−lenfa1,posfa] 中有两个儿子 sss就令 ansfa1→anssans_{fa}1\to ans_{s}ansfa1→anss。 但是仔细想想还会有一些问题 比如可能会跳两次才可以转移但是连续的父子之间都无法构成二倍关系。这个不麻烦记录一下上一次成功转移的 preprepre每次判断 [pospre−lenpre1,pospre][pos_{pre}-len_{pre}1,pos_{pre}][pospre−lenpre1,pospre] 即可
还有一个问题我们这里的 lenlenlen 都是最长长度会不会有一个同一等价类里较短的子串可以转移而那个最长子串无法转移呢 不会 考虑反证证明 假设有子串
AcAAA 其中1、2属于同一等价类2无法转移到3而1可以 那么必然有串cAA这样12才能是一个等价类 又由于3是该等价类最长字符串所以AA和cAA不属于同一等价类 也就是说有一个位置出现了AA却没有出现cAA那么这个地方第一个A的位置也会出现了A却没有出现cA 所以1、2不在一个等价类里与题设矛盾原命题得证
代码
#includebits/stdc.h
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N4e5100;
const int mod1e97;
inline ll read(){ll x(0),f(1);char cgetchar();while(!isdigit(c)){if(c-)f-1;cgetchar();}while(isdigit(c)){x(x1)(x3)c-0;cgetchar();}return x*f;
}
int n,m;int ed[N];
struct SAM{struct node{int len,fa;int tr[26];}st[N];int lst1,tot1;int pl[N];inline void ins(int c,int o){c-a;int curtot,plst;lsttot;ed[cur]o;st[cur].lenst[p].len1;for(;p!st[p].tr[c];pst[p].fa) st[p].tr[c]cur;if(!st[p].tr[c]) st[cur].fa1;else{int qst[p].tr[c];if(st[q].lenst[p].len1) st[cur].faq;else{int pptot;st[pp]st[q];ed[pp]ed[q];st[pp].lenst[p].len1;st[cur].fast[q].fapp;for(;pst[p].tr[c]q;pst[p].fa) st[p].tr[c]pp;}}}void print(){for(int i1;itot;i){printf(i%d fa%d len%d ed%d\n,i,st[i].fa,st[i].len,ed[i]);}putchar(\n);return;}
}s;struct segmentTree{#define mid ((lr)1)struct tree{int ls,rs,siz;}tr[N6];int rt[N],tot;inline int copy(int x){tr[tot]tr[x];return tot;}inline void pushup(int k){tr[k].siztr[tr[k].ls].siztr[tr[k].rs].siz;return;}void add(int k,int l,int r,int p){if(!k) kcopy(0);if(lr){tr[k].siz;return;}if(pmid) add(tr[k].ls,l,mid,p);else add(tr[k].rs,mid1,r,p);pushup(k);}int merge(int a,int b,int l,int r){if(!a||!b) return a|b;acopy(a);if(lr){tr[a].siztr[b].siz;return a;}tr[a].lsmerge(tr[a].ls,tr[b].ls,l,mid);tr[a].rsmerge(tr[a].rs,tr[b].rs,mid1,r);pushup(a);return a;}int ask(int k,int l,int r,int x,int y){if(xy) return 0;if(!k) return 0;if(xlry) return tr[k].siz;int res(0);if(xmid) resask(tr[k].ls,l,mid,x,y);if(ymid) resask(tr[k].rs,mid1,r,x,y);return res;}
}t;char ss[N];vectorintv[N];
int dp[N],pre[N];
void dfs1(int x){if(ed[x]) t.add(t.rt[x],1,n,ed[x]);for(int to:v[x]){//printf(%d - %d\n,x,to);dfs1(to);t.rt[x]t.merge(t.rt[x],t.rt[to],1,n);}return;
}
int ans;
void dfs2(int x){//printf(x%d dp%d pre%d\n,x,dp[x],pre[x]);ansmax(ans,dp[x]);for(int to:v[x]){//printf( %d - %d 1? (%d %d)\n,x,to,ed[to]-s.st[to].lens.st[pre[x]].len,ed[to]-1);if(x1||(ed[to]t.ask(t.rt[pre[x]],1,n,ed[to]-s.st[to].lens.st[pre[x]].len,ed[to]-1))){dp[to]dp[x]1;pre[to]to;}else dp[to]dp[x],pre[to]pre[x];dfs2(to);}return;
}
signed main() {
#ifndef ONLINE_JUDGE//freopen(a.in,r,stdin);//freopen(a.out,w,stdout);
#endif
//printf(%d\n,sizeof(t)/1024/1024);nread();scanf( %s,ss1);for(int i1;in;i) s.ins(ss[i],i);//s.print();for(int i2;is.tot;i) v[s.st[i].fa].push_back(i);dfs1(1);dfs2(1);printf(%d\n,ans);return 0;
}
/*
21
abcaaaaabbcbacbabcbcb*/