zoukankan      html  css  js  c++  java
  • P4248 [AHOI2013]差异(后缀树)

    P4248 [AHOI2013]差异

    给出一个长度为\(n\)的字符串\(S\),令\(T_i\)表示它从第\(i\)个字符开始的后缀,求:

    \(\sum_{1\leq i<j\leq n}len(T_i)+len(T_j)-2\times lcp(T_i,T_j)\)

    做法:

    对反串建后缀树。

    后缀树的边权记为\(len[i]-len[link[i]]\)

    求后缀树上所有路径长度和,就是答案。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    int nxt[maxn][26],link[maxn],len[maxn],sz[maxn],tot=1,lst=1;
    string s;
    
    void sam_extend (char c) {
    	int cur=++tot,p=lst;
    	sz[cur]=1;
    	len[cur]=len[lst]+1;
    	sz[cur]=1;
    	while (p&&!nxt[p][c-'a']) {
    		nxt[p][c-'a']=cur;
    		p=link[p];
    	}
    	if (!p) link[cur]=1;
    	else {
    		int q=nxt[p][c-'a'];
    		if (len[p]+1==len[q]) link[cur]=q;
    		else {
    			int clone=++tot;
    			len[clone]=len[p]+1;
    			for (int i=0;i<26;i++) nxt[clone][i]=nxt[q][i];
    			link[clone]=link[q];
    			while (p&&nxt[p][c-'a']==q) {
    				nxt[p][c-'a']=clone;
    				p=link[p];
    			}
    			link[q]=link[cur]=clone;
    		}
    	}
    	lst=cur;
    }
    vector<int> g[maxn];
    void dfs (int u) {
    	for (int v:g[u]) {
    		dfs(v);
    		sz[u]+=sz[v];
    	}
    }
    int main () {
    	ios::sync_with_stdio(false);
    	cin>>s;
    	int n=s.size();
    	for (int i=s.size()-1;i>=0;i--) {
    		sam_extend(s[i]);
    	}
    	for (int i=2;i<=tot;i++) g[link[i]].push_back(i);
    	dfs(1);
    	long long ans=0;
    	for (int i=2;i<=tot;i++) {
    		ans+=1ll*sz[i]*(n-sz[i])*(len[i]-len[link[i]]);
    	}
    	printf("%lld\n",ans);
    }
    
  • 相关阅读:
    Hadoop深入学习:MapTask详解
    设计模式系列——三个工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
    GIT使用教程与基本原理
    网络爬虫浅析
    字符串模式匹配sunday算法
    linux ---- diff命令
    递归树的算法分析
    二叉树非递归实现
    链表相邻元素交换
    明星问题
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15515382.html
Copyright © 2011-2022 走看看