谁爱调谁调去,我他妈才不调这么傻逼的代码.
code:
#include <cstdio> #include <algorithm> #include <cstring> #include <string> #include <vector> #include <map> #define N 100007 #define inf 0x3f3f3f3f #define ull unsigned long long // 代码已写完,人已阵亡. using namespace std; int K1,K2; ull ans,W; char S[N]; namespace IO { void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); // freopen(out.c_str(),"w",stdout); } }; struct SAM { #define M N<<1 int tot,last; struct Edge { int to,w; Edge(int to=0,int w=0):to(to),w(w){} }; vector<Edge>G[M]; int pre[M],ch[M][26],mx[M],str_sam[M],sam_str[M],depth[M]; void Initialize() { tot=last=1; } void extend(int c) { int np=++tot,p=last; mx[np]=mx[p]+1,last=np; for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np; if(!p) pre[np]=1; else { int q=ch[p][c]; if(mx[q]==mx[p]+1) pre[np]=q; else { int nq=++tot; mx[nq]=mx[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); pre[nq]=pre[q],pre[np]=pre[q]=nq; for(;p&&ch[p][c]==q;p=pre[p]) ch[p][c]=nq; } } } void Build_LCP() { int n=strlen(S+1),i,j,p=1; for(i=1;i<=n;++i) { p=ch[p][S[n-i+1]-'a']; sam_str[p]=n-i+1; str_sam[n-i+1]=p; } for(i=2;i<=tot;++i) { if(mx[i]>K1) depth[i]=0; else depth[i]=mx[i]; } for(i=2;i<=tot;++i) G[pre[i]].push_back(Edge(i,depth[i]-depth[pre[i]])); } void Build_LCS() { int n=strlen(S+1),i,j,p=1; for(i=1;i<=n;++i) { p=ch[p][S[i]-'a']; sam_str[p]=i; str_sam[i]=p; } for(i=2;i<=tot;++i) { if(mx[i]>K2) depth[i]=0; else depth[i]=mx[i]; } for(i=2;i<=tot;++i) G[pre[i]].push_back(Edge(i,depth[i]-depth[pre[i]])); } #undef M }lcp,lcs; namespace vir { vector<int>G[N<<1]; int t,sta,tot; int is1[N],is2[N]; int dfn[N],S[N],dep[N],size[N],son[N],top[N],f[N],val[N],col[N],re[N]; ull size1[N],size2[N],sizew[N]; ull sum1[N],sum2[N],sumw[N]; bool cmp(int a,int b) { return dfn[a]<dfn[b]; } void get_dfn(int x,int fa) { dfn[x]=++t; size[x]=1; f[x]=fa; for(int i=0;i<lcp.G[x].size();++i) { int y=lcp.G[x][i].to; if(y==fa) continue; get_dfn(y,x); dep[y]=dep[x]+1; size[x]+=size[y]; if(size[y]>size[son[x]]) son[x]=y; } } void dfs2(int u,int tp) { top[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=0;i<lcp.G[u].size();++i) { int v=lcp.G[u][i].to; if(v==son[u]||v==f[u]) continue; dfs2(v,v); } } int LCA(int x,int y) { while(top[x]!=top[y]) { dep[top[x]]>dep[top[y]]?x=f[top[x]]:y=f[top[y]]; } return dep[x]<dep[y]?x:y; } void _new(int x,int v,int c) { ++tot; re[tot]=x; val[x]=v; col[x]=c; if(c==1) is1[x]=1; else is2[x]=1; } void addvir(int x,int y) { G[x].push_back(y); } void Initialize() { t=0; get_dfn(1,0); dfs2(1,1); } void Insert(int x) { if(sta<=1) { S[++sta]=x; return; } int lca=LCA(S[sta],x); if(lca==S[sta]) S[++sta]=x; else { while(sta>1&&dep[S[sta-1]]>=dep[lca]) addvir(S[sta-1],S[sta]),--sta; if(S[sta]==lca) S[++sta]=x; else { addvir(lca,S[sta]); S[sta]=lca; S[++sta]=x; } } } void Build() { sta=0; sort(re+1,re+1+tot,cmp); if(re[1]!=1) S[++sta]=1; for(int i=1;i<=tot;++i) Insert(re[i]); while(sta>1) addvir(S[sta-1],S[sta]),--sta; } void DP(int x) { for(int i=0;i<G[x].size();++i) { int y=G[x][i]; DP(y); size1[x]+=size1[y]; size2[x]+=size2[y]; sum1[x]+=sum1[y]; sum2[x]+=sum2[y]; } ull tmp=0; ull cntw=0; ull cur=0; for(int i=0;i<G[x].size();++i) { int y=G[x][i]; tmp+=(sum1[x]-sum1[y])*size2[y]; tmp+=(sum2[x]-sum2[y])*size1[y]; cntw+=(size1[x]-size1[y])*size2[y]; } cur+=(tmp)*lcp.depth[x]; cur-=(cntw)*W*lcp.depth[x]; cur+=is1[x]*size2[x]*val[x]*lcp.depth[x]+is2[x]*size1[x]*val[x]*lcp.depth[x]; cur-=(is1[x]*size2[x]*W+is2[x]*size1[x]*W); ans+=cur/2; size1[x]+=is1[x]; size2[x]+=is2[x]; sum1[x]+=is1[x]*val[x]; sum2[x]+=is2[x]*val[x]; } void solve() { Build(); DP(1); for(int i=1;i<=tot;++i) { re[i]=val[i]=sum1[i]=sum2[i]=size1[i]=size2[i]=is1[i]=is2[i]=0; G[i].clear(); re[i]=0; } tot=0; sta=0; } }; // 虚树 int tot,edges=1; int totsize,rt1,rt2,mx,ed,lsc,rsc; int hd[N<<3],vis[N<<3],size[N<<3]; struct Edge { int to,w,nex; }e[N<<3]; struct Node { int u,dis,val; Node(int u=0,int dis=0,int val=0):u(u),dis(dis),val(val){} }L[N<<2],R[N<<2]; void add_div(int x,int y,int z) { e[++edges].nex=hd[x],hd[x]=edges,e[edges].to=y,e[edges].w=z; } void Build_Tree(int x,int fa) { int ff=0; for(int i=0;i<lcs.G[x].size();++i) { int y=lcs.G[x][i].to; if(y==fa) continue; if(!ff) { ff=x; add_div(ff,y,lcs.G[x][i].w); add_div(y,ff,lcs.G[x][i].w); } else { ++tot; add_div(ff,tot,0); add_div(tot,ff,0); add_div(tot,y,lcs.G[x][i].w); add_div(y,tot,lcs.G[x][i].w); ff=tot; } Build_Tree(y,x); } } void find_edge(int x,int fa) { size[x]=1; for(int i=hd[x];i;i=e[i].nex) { int y=e[i].to; if(y==fa||vis[i]) continue; find_edge(y,x); size[x]+=size[y]; int now=max(size[y],totsize-size[y]); if(now<mx) { mx=now; ed=i; rt1=x,rt2=y; } } } void get_node(int x,int fa,int dep,int ty) { if(ty==0) { if(lcs.sam_str[x]) L[++lsc]=Node(lcs.sam_str[x],lcs.mx[x]-dep,dep); } else { if(lcs.sam_str[x]) R[++rsc]=Node(lcs.sam_str[x],lcs.mx[x]-dep,dep); } for(int i=0;i<lcs.G[x].size();++i) { int y=lcs.G[x][i].to; if(vis[i]||y==fa) continue; get_node(y,x,dep+lcs.G[x][i].w,ty); } } void Divide_And_conquer(int x) { if(totsize==1) return; mx=inf; rt1=rt2=ed=0; find_edge(x,0); vis[ed]=vis[ed^1]=1; lsc=rsc=0; get_node(rt1,0,0,1); get_node(rt2,0,0,2); for(int i=1;i<=lsc;++i) vir::_new(lcp.str_sam[L[i].u],L[i].dis,1); for(int i=1;i<=rsc;++i) vir::_new(lcp.str_sam[R[i].u],R[i].dis,2); W=e[ed].w; vir::solve(); int tmprt1=rt1,tmprt2=rt2; int sizert1=size[rt1],sizert2=totsize-size[rt1]; totsize=sizert1; Divide_And_conquer(tmprt1); totsize=sizert2; Divide_And_conquer(tmprt2); } int main() { IO::setIO("input"); int i,j,n; scanf("%s%d%d",S+1,&K1,&K2); n=strlen(S+1); lcp.Initialize(); lcs.Initialize(); for(i=1;i<=n;++i) { lcs.extend(S[i]-'a'); lcp.extend(S[n-i+1]-'a'); } lcs.Build_LCS(); lcp.Build_LCP(); tot=lcs.tot; Build_Tree(1,0); vir::Initialize(); totsize=n; printf("%llu\n",ans); return 0; }