【BZOJ3238】【AHOI2013】差异

sam好,好写好调好ac!

原题:

图片题面好评

2<=N<=500000

在syq大神的指点下终于理解一道后缀自动姬了quq

(其实是因为这道题的dp主要是在后缀树(就是拓扑序)上搞树形dp……

恩sam有个好玩的东西呢就是搞出后缀自动姬后根据max搞一个类似与后缀数组中countrank的东西

这个就是自动姬的拓扑序,同时也是parent树的不知道什么序,反正如果倒叙遍历这个序列的话x一定会比father[x]先访问到就对了

然后就可以直接用countrank搞树形dp辣

每个树点对答案的贡献就是(max[x]-max[father[x]])*C_{|right[x]|}^{2}

写到这里我突然发现这个组合数不太理解啊,如果两个节点在同一个子节点的子树中怎么办……

一定是还有什么性质我没考虑到

syq回寝吃泡面了,只能回去问syq了quq

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 int rd(){int z=0,mk=1;  char ch=getchar();
 9     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)mk=-1;  ch=getchar();}
10     while(ch>=‘0‘&&ch<=‘9‘){z=(z<<3)+(z<<1)+ch-‘0‘;  ch=getchar();}
11     return z*mk;
12 }
13 char s[510000];  int n;
14 int nxt[1100000][26],fa[1100000],mx[1100000],sz[1100000],sm[1100000];
15 int lst=1,tt=1;
16 int cnt[1100000],cntrk[1100000];
17 void ist(int x){
18     int p=lst,np=lst=++tt;
19     mx[np]=mx[p]+1;  sz[np]=sm[np]=1;
20     while(!nxt[p][x] && p)  nxt[p][x]=np,p=fa[p];
21     if(!p)  fa[np]=1;
22     else{
23         int q=nxt[p][x];
24         if(mx[p]+1==mx[q])  fa[np]=q;
25         else{
26             int nq=++tt;  mx[nq]=mx[p]+1;
27             memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
28             fa[nq]=fa[q];  fa[q]=fa[np]=nq;
29             while(nxt[p][x]==q)  nxt[p][x]=nq,p=fa[p];
30         }
31     }
32 }
33 void gtcntrk(){
34     for(int i=1;i<=tt;++i)  ++cnt[mx[i]];
35     for(int i=1;i<=n;++i)  cnt[i]+=cnt[i-1];
36     for(int i=tt;i;--i)  cntrk[cnt[mx[i]]--]=i;
37 }
38 ll play(){
39     ll bwl=0;
40     for(int i=tt;i;--i){
41         sz[fa[cntrk[i]]]+=sz[cntrk[i]];
42         /*bwl+=(ll)sm[fa[cntrk[i]]]*sz[cntrk[i]]*mx[fa[cntrk[i]]];
43         sm[fa[cntrk[i]]]+=sz[cntrk[i]];*/
44         bwl+=(ll)(mx[cntrk[i]]-mx[fa[cntrk[i]]])*sz[cntrk[i]]*(sz[cntrk[i]]-1);
45     }
46     return bwl;
47 }
48 int main(){//freopen("ddd.in","r",stdin);
49     scanf("%s",s+1);  n=strlen(s+1);
50     for(int i=1;i<=n;++i)  ist(s[i]-‘a‘);
51     gtcntrk();
52     cout<<(ll)(n+1)*n/2*(n-1)-play()<<endl;
53     return 0;
54 }

时间: 2024-08-05 01:37:59

【BZOJ3238】【AHOI2013】差异的相关文章

bzoj3238 [Ahoi2013]差异 后缀数组+单调栈

[bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 题解: 任意两个字符串的lcp是什么,就是如 a,b  那么若a==b 那么为len(a) 否则设sa[a]<sa[b] 那么为min(height[sa[a]+1-------sa[b]]) 1 #include<cstring> 2 #include<iostrea

BZOJ3238: [Ahoi2013]差异

3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 437  Solved: 213[Submit][Status]Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacaoSample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 题解: 刚看到题目,想着求出height然后搞出每个点作为最小值向右向左拓

BZOJ3238: [Ahoi2013]差异 (后缀自动机)

Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 YY了后缀自动机的解法: 首先题意就是让你求sigma(LCP(i,j)|i<j) 将字符串反过来,考虑两个后缀对答案的贡献,其实就是节点x和y的lca节点包含的最长子串长度 那么将SAM构出来,考虑当LCA为节点z时,有多少满足条件的(x,y),这个枚举z的相邻

【BZOJ 3238】 3238: [Ahoi2013]差异(SAM)

3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3047  Solved: 1375 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 Source [分析] 这题先把sigma len 加上. 然后考虑一下减掉的是什么. 对于每个子

【BZOJ 3238】 [Ahoi2013]差异

3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 777 Solved: 359 [Submit][Status][Discuss] Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 后缀数组+单调队列. 式子中前两项的和可以直接求出为

bzoj 3238: [Ahoi2013]差异 -- 后缀数组

3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 Source 后缀数组+单调栈水过... #include<map> #include<cmath> #include<

【BZOJ3238】差异(后缀自动机)

[BZOJ3238]差异(后缀自动机) 题面 BZOJ 题解 前面的东西直接暴力算就行了 其实没必要算的正正好 为了方便的后面的计算 我们不考虑\(i,j\)的顺序问题 也就是先求出\(\sum_{i=1}^n\sum_{j=1}^n[i\neq j]len[i]\) 然后对于每个后缀树上的节点,减去一下贡献 也就是\(size[i]*(size[i]-1)*(len[i]-len[i.parent])\) 这样的话,就很容易计算了.. 我知道我写的一点都不清楚 构建出\(SAM\)后,\(pa

P4248 [AHOI2013]差异 解题报告

P4248 [AHOI2013]差异 题目描述 给定一个长度为 \(n\) 的字符串 \(S\),令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀.求 \[\displaystyle \sum_{1\leqslant i<j\leqslant n}\text{len}(T_i)+\text{len}(T_j)-2\times\text{lcp}(T_i,T_j)\] 其中,\(\text{len}(a)\)表示字符串 \(a\) 的长度,\(\text{lcp}(a,b)\) 表示字

【AHOI2013】【BZOJ3238】差异

Description Input 一行,一个字符串S Output 一行.一个整数.表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 后缀自己主动机的性质: 5.两个串的最长公共后缀,位于这两个串相应状态在Parent树上的近期公共祖先状态. 那么我们把原题里后缀的最长公共前缀反过来,把原串反过来建SAM就变成了最长公共后缀 然后题意就是求一个串全部前缀的最长公共后缀长度之和 我们能够在parent树

【bzoj3238】[Ahoi2013]差异 后缀数组+单调栈

题目描述 输入 一行,一个字符串S 输出 一行,一个整数,表示所求值 样例输入 cacao 样例输出 54 题解 后缀数组+单调栈,几乎同 bzoj3879 的后半部分. 我明显是做题做反了... 这里还是说一下这道题的做法. 先用后缀数组求出height. 然后由于有LCP(a,c)=min(LCP(a,b),LCP(b,c))(rank[a]<rank[b]<rank[c]),所以我们只需要知道排名相邻的两个后缀的LCP,而这就是height数组的定义. 转化为子问题:给出n个数,求所有子