转载请注明出处谢谢、、http://blog.csdn.net/vmurder/article/details/42721101
首先 秦神QY Orz
题解:
这道题后缀数组过于鬼畜(wo’tai’ruo’bu’gan’xie)
所以写了简单好写易于理解不用分治不用RMQ的SAM大叔。
题解:
首先其实我们需要一个后缀树,然后两个后缀的lcp就是它们lca的len。
后缀树可以通过反序后缀自动机得到,这个很水。
然后len的性质就是后缀自动机的那个len(我写的‘deep’)。
后缀树上DP就水了,随便乱搞就可以过了。
那个size[x]*size[x-1]是C(size[x],2)的意思。
分析:一个节点(状态)的deep就是以他为结束的最长子串长度,当然就是那个lca了233。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 1001000 #define T 26 using namespace std; struct KSD { int v,next; }e[N]; int head[N],cnt; inline void add(int u,int v) { cnt++; e[cnt].v=v; e[cnt].next=head[u]; head[u]=cnt; } int size[N]; int pa[N],son[N][T],dep[N]; int tot=1,last=1; inline int newnode(int _dep){dep[++tot]=_dep;return tot;} inline void SAM(int alp) { int p=newnode(dep[last]+1); size[p]=1; int u=last; while(u&&!son[u][alp])son[u][alp]=p,u=pa[u]; if(!u)pa[p]=1; else { int v=son[u][alp]; if(dep[v]==dep[u]+1)pa[p]=v; else { int nv=newnode(dep[u]+1); pa[nv]=pa[v],pa[v]=pa[p]=nv; memcpy(son[nv],son[v],sizeof son[nv]); while(u&&son[u][alp]==v)son[u][alp]=nv,u=pa[u]; } } last=p; } long long ans; void tree_dp(int x,int p) { int i,v; for(i=head[x];i;i=e[i].next) { tree_dp(v=e[i].v,x); size[x]+=size[v]; } dep[x]-=dep[p]; ans-=(long long)size[x]*(size[x]-1)*dep[x]; } char str[N]; int main() { // freopen("test.in","r",stdin); int i,j,k; scanf("%s",str); int len=strlen(str); for(i=len-1;i>=0;i--)SAM(str[i]-'a'); ans=(long long)(len-1)*len*(len+1)>>1; for(i=2;i<=tot;i++)add(pa[i],i); for(i=head[1];i;i=e[i].next)tree_dp(e[i].v,1); cout<<ans<<endl; return 0; }
时间: 2024-10-05 21:37:29