【BZOJ】 3238: [Ahoi2013]差异

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3238


求:$${\sum _{i=1}^{n-1}\sum _{j=i+1}^{n}len(T_i)len(T_j)-2lcp(T_i,T_j)}$$

  $T_i$表示从第$i$个字符开始的后缀。


原式${=n(n+1)(n-1)-\sum _{i=1}^{n-1}\sum _{j=i+1}^{n}2lcp(T_i,T_j)}$

 

  这不就是NOI2015品酒大会的第一问啦,利用SAM构出后缀树,每个后缀对应一个后缀树上的点,${lcp(x,y)=deep[lca(x,y)]}$,树形统计一下即可。


 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 500010*2
10 #define llg long long 
11 #define SIZE 26
12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
13 llg n,m,ans,ans1[maxn],size[maxn];
14 char s[maxn];
15 
16 struct SAM
17 {
18     struct 
19     {
20         llg len,f,ch[SIZE];
21         void init()
22         {
23             len=0,f=-1;
24             memset(ch,0xff,sizeof(ch));
25         }
26     }e[maxn<<1];
27 
28     vector<llg>a[maxn<<1];
29     llg idx,last,size[maxn<<1];
30 
31     void init(){idx=last=0; e[idx++].init(); memset(size,0,sizeof(size));}
32 
33     llg newnode() {e[idx].init(); return idx++;}
34 
35     void insert(llg c)
36     {
37         llg end=newnode(),tmp=last;
38         e[end].len=e[last].len+1; size[end]=1;
39         for (;tmp!=-1 && e[tmp].ch[c]==-1;tmp=e[tmp].f) e[tmp].ch[c]=end;
40         if (tmp==-1) e[end].f=0;
41         else
42         {
43             llg nxt=e[tmp].ch[c];
44             if (e[tmp].len+1==e[nxt].len) e[end].f=nxt;
45             else
46             {
47                 llg np=newnode();
48                 e[np]=e[nxt];
49                 e[np].len=e[tmp].len+1;
50                 e[nxt].f=e[end].f=np;
51                 for (;tmp!=-1 && e[tmp].ch[c]==nxt;tmp=e[tmp].f) e[tmp].ch[c]=np;
52             }
53         }
54         last=end;
55     }
56 
57     void link_fa() {for (llg i=1;i<idx;i++) a[e[i].f].push_back(i);}
58 
59     void dp(llg x)
60     {
61         llg w=a[x].size(),v;
62         for (llg i=0;i<w;i++) dp(a[x][i]);
63         for (llg i=0;i<w;i++)
64         {
65             v=a[x][i];
66             ans1[e[x].len]+=size[x]*size[v];
67             size[x]+=size[v];
68         }
69     }
70 
71 }sam;
72 
73 int main()
74 {
75     yyj("bzoj3238");
76     scanf("%s",s);
77     n=strlen(s);
78     sam.init();
79     for (llg i=n-1;i>=0;i--) sam.insert(s[i]-'a');
80     sam.link_fa();
81     sam.dp(0);
82     ans=n*(n+1)*(n-1);
83     ans/=2;
84     for (llg i=1;i<=n;i++) ans-=i*ans1[i]*2;
85     cout<<ans<<endl;
86     return 0;
87 }

 

posted @ 2017-02-10 11:07  №〓→龙光←  阅读(160)  评论(0编辑  收藏  举报