【BZOJ3238】【Ahoi2013】差异 后缀自动机

转载请注明出处谢谢、、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

【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

BZOJ 3238 AHOI2013 差异 后缀自动机

题目大意:给定一个字符串,求Σ[1<=i<j<=n]|Ti|+|Tj|-2|LCP(Ti,Tj)| 前两项是可以O(1)求的 我们要求的就是LCP之和 对反串建立后缀自动机 那么parent指针连成的树就是后缀树 直接在后缀树上DP就行- - 对于每个节点统计所有子树两两right集合大小乘积之和乘上这个节点的深度即可 QY神在学校讲了一天的SAM... 现在我觉得我还是回去学大型建筑机械吧233- - #include <map> #include <vector&g

BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp

http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有两幅面孔呢). 看代码实现吧,不大容易口头解释,把加的和减的分开算就可以了,减去的通过倒着建sam(相当于建一棵后缀树),然后算每个len取的次数实现,注意树归中一些避免重复操作. 1 /********************************************************

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的相邻

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然后搞出每个点作为最小值向右向左拓

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】[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个数,求所有子

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

题目链接 Description 一个长度为\(n\)的字符串\(S\),令\(T_i\)表示它从第\(i\)个字符开始的后缀.求\[\sum_{1\leq i\leq j\leq n}len(T_i)+len(T_j)-2*lcp(T_i,T_j)\]其中,\(len(a)\)表示字符串\(a\)的长度,\(lcp(a,b)\)表示字符串\(a\)和字符串\(b\)的最长公共前缀. \(2\leq n\leq 500000\) 思路 \(O(n^2)\)枚举显然是不可行的,应从 贡献 的角度取

【BZOJ 3238】差异 后缀自动机+树形DP

题意 给定字符串,令$s_i$表示第$i$位开始的后缀,求$\sum_{1\le i < j \le n} len(s_i)+len(s_j)-2\times lcp(s_i,s_j)$ 先考虑前面的和式,直接计算为$\frac{n(n^2-1)}{2}$,考虑后面的和式,$lcp$相关可以用sam求解,sam形成的parent树是原串的前缀树,所以两个串的最长公共后缀是在parent树上最近公共祖先对应的状态的长度$maxlen_s-maxlen_{pa_s}$,将原串反向建立sam得到后缀树