zoukankan      html  css  js  c++  java
  • 后缀自动机转后缀树模板

    终于找到教程了,现在来写一发

    题目:Jzoj4072(bzoj3998)弦论 第一问

    其实非常好写,连空间都不需要多开一倍,只需要sa数组rank数组和height数组就好了,dfs一次可以求出


    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<algorithm>
    #define N 1000010
    using namespace std;
    char str[N]; long long k,c[N];
    int s[N][26],f[N],sz[N],l[N],mx[N];
    int n,m,cnt=1,lst=1,tot=0,sa[N],r[N],h[N];
    inline int extend(char c,int pos){
    	int p=lst,np=lst=++cnt,q,nq; c-='a';
    	mx[np]=mx[p]+1; sz[np]=1; l[np]=pos;
    	for(;p&&!s[p][c];p=f[p]) s[p][c]=np;
    	if(!p) return f[np]=1;
    	q=s[p][c];
    	if(mx[q]==mx[p]+1) f[np]=q;
    	else{
    		nq=++cnt;
    		mx[nq]=mx[p]+1; l[nq]=l[q];
    		f[nq]=f[q]; f[q]=f[np]=nq;
    		memcpy(s[nq],s[q],26<<2);
    		for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq;
    	}
    }
    void dfs(int x){
    	if(sz[x]) sa[++tot]=l[x],r[l[x]]=tot;
    	for(int i=0;i<26;++i) if(s[x][i]) dfs(s[x][i]);
    }
    int main(){
    	scanf("%s%d%lld",str+1,&m,&k);
    	for(int i=n=strlen(str+1);i;--i) extend(str[i],i);
    	memset(s,0,sizeof s);
    	for(int i=2;i<=cnt;++i) s[f[i]][str[l[i]+mx[f[i]]]-'a']=i;
    	dfs(1);
    	for(int i=1,j,k=0;i<=n;++i) 
    		if(r[i]>1){
    			for(k?--k:0,j=sa[r[i]-1];str[i+k]==str[j+k];++k);
    			h[r[i]]=k;
    		}
    	if(m) for(int i=1;i<=n;++i) c[i]=c[i-1]+n-sa[i]+1;
    	else for(int i=1;i<=n;++i) c[i]=c[i-1]+n-sa[i]+1-h[i];
    	if(k>c[n]) puts("-1"); else {
    		int j=lower_bound(c+1,c+1+n,k)-c;
    		while(c[j]>k) --j; str[k-c[j]+sa[j+1]+h[j+1]]=0;
    		printf("%s",str+sa[j+1]);
    	}
    }

  • 相关阅读:
    电路学习实战分析之mos-2
    我这博客咋分类的?
    学习shell之后,实战分析
    二叉树,二叉排序树,红黑树 学习
    哈希表 学习
    《转》C语言可变参函数的实现
    Linux工具记录
    苏州之旅有感
    git 命令动画学
    软件工程相关博客
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8312579.html
Copyright © 2011-2022 走看看