• AHOI2013 差异


    (SAM)中比较简单的题.
    题目链接
    其实这道题有一种用时间换空间的(SA)做法.
    就是把(Height)建出来之后从大到小做,用一个并查集记录(size)即可.
    时间复杂度(O(n*log n)),空间复杂度(O(n))
    (SAM)的话就枚举一个点,算一下有多少种方案可以使两个点的(lca)是它即可.
    算出方案再乘上(len)就好了.
    时间复杂度(O(n)),空间复杂度(O(n*26))

    代码如下

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #define N (2000010)
    #define M (N<<1)
    #define inf (0x7f7f7f7f)
    #define rg register int
    #define Label puts("NAIVE")
    #define spa print(' ')
    #define ent print('
    ')
    #define rand() (((rand())<<(15))^(rand()))
    typedef long double ld;
    typedef long long LL;
    typedef unsigned long long ull;
    using namespace std;
    char s[N]; int n; LL ans;
    struct SAM{
    	int fa[N],ch[N][26],len[N],siz[N];
    	int lst,cnt,fi[N],ne[M],b[M],E;
    	SAM(){lst=cnt=1;}
    	void add(int x,int y){
    		ne[++E]=fi[x],fi[x]=E,b[E]=y;
    	}
    	void insert(int w,int L){
    		int u=lst;len[lst=++cnt]=L,siz[cnt]=1;
    		for(;u&&!ch[u][w];u=fa[u])ch[u][w]=cnt;
    		if(!u){fa[cnt]=1;return;}
    		int s=ch[u][w];
    		if(len[u]+1==len[s]){fa[cnt]=s;return;}
    		len[++cnt]=len[u]+1;
    		for(int i=0;i<26;i++)ch[cnt][i]=ch[s][i];
    		fa[cnt]=fa[s],fa[s]=fa[lst]=cnt;
    		for(int i=u;ch[i][w]==s;i=fa[i])ch[i][w]=cnt;
    	}
    	void build(){for(int i=2;i<=cnt;i++)add(fa[i],i);}
    	void solve(int u){
    		for(int i=fi[u];i;i=ne[i]){
    			int v=b[i]; solve(v);
    			ans+=1ll*siz[v]*siz[u]*len[u],siz[u]+=siz[v];
    		}
    	}
    }S;
    int main(){
    	scanf("%s",s+1),n=strlen(s+1);
    	for(int i=1;i<=n;i++)S.insert(s[i]-'a',i);
    	S.build(),S.solve(1);
    	printf("%lld
    ",1ll*(n-1)*n*(n+1)/2-2*ans);
    }
    
  • 相关阅读:
    协议与接口相关
    jmeter 使用(1)
    jmeter 压力测试
    shell脚本的规则
    charles的原理及使用
    Linux环境部署和项目构建
    面向对象
    python 基础练习题
    jmeter 使用(2)
    Ext.apply
  • 原文地址:https://www.cnblogs.com/Romeolong/p/10158459.html
Copyright © 2020-2023  润新知