BZOJ 3238: [Ahoi2013]差异【S(后)A(缀)M(树)上DP

来源:互联网 发布:怎么注册淘宝云客服 编辑:程序博客网 时间:2024/04/20 11:55

啊我又在写SAM……

反正题里求的就是反串后缀树上的各关键点之间的路径长度和

于是……dp一下

像我比较菜……

在本题rank1的lxl大爷的指导下

……嗯每条边出现的次数就是子树里关键点个数siz[i]*(n-siz[i])……显然…………嗨呀我好菜啊QAQ这都看不出来QAQ看来是要退役了

啊……反正这样写常数还是……不大的吧?

#include<bits/stdc++.h>//#define Flaze_naive#define MAXN 500005using namespace std;char read_s[MAXN];struct sam{int son[MAXN<<1][26],pre[MAXN<<1],dis[MAXN<<1];int Right[MAXN<<1];int p,np,q,nq,lst,cnt;int lth;void insert(int x){dis[np=++cnt]=dis[p=lst]+1;Right[np]=1,lst=np;for(;p&&!son[p][x];p=pre[p])son[p][x]=np;if(!p)return pre[np]=1,void();q=son[p][x];if(dis[q]==dis[p]+1)return pre[np]=q,void();else{dis[nq=++cnt]=dis[p]+1;memcpy(son[nq],son[q],sizeof son[q]);pre[nq]=pre[q];pre[q]=pre[np]=nq;for(;p&&son[p][x]==q;p=pre[p])son[p][x]=nq;}}void build(){lst=cnt=1;scanf("%s",read_s);lth=strlen(read_s);for(int i=0;i<lth;++i)insert(read_s[i]-'a');}void build_(){lst=cnt=1;scanf("%s",read_s);lth=strlen(read_s);for(int i=lth-1;~i;--i)insert(read_s[i]-'a');}int s[MAXN<<1],v[MAXN<<1];void sort(){for(int i=1;i<=cnt;++i)++v[dis[i]];for(int i=1;i<=lth;++i)v[i]+=v[i-1];for(int i=1;i<=cnt;++i)s[v[dis[i]]--]=i;}long long ans;void DP(){for(int i=cnt;i;--i){int now=s[i],fth=pre[now];Right[fth]+=Right[now];ans+=1ll*(dis[now]-dis[fth])*Right[now]*(lth-Right[now]);//int now=s[i],fth=pre[now],tmp=dis[now]-dis[fth];//sum[now]+=Right[now]*tmp;//ans+=sum[now]*Right[fth]+sum[fth]*Right[now];//Right[fth]+=Right[now],sum[fth]+=sum[now];}}#ifdef Flaze_naivechar tmp[MAXN<<1];void dfs(int now,int stp){puts(tmp);for(int i=0;i<26;++i)if(son[now][i])tmp[stp]='a'+i,dfs(son[now][i],stp+1);tmp[stp]=' ';}#endif }SAM;int main(){SAM.build_();#ifdef Flaze_naiveSAM.dfs(1,0);#endif SAM.sort();SAM.DP();printf("%lld",SAM.ans);return 0;}


0 0