• P3975 [TJOI2015]弦论(后缀自动机)


    对于t=0的情况:

    在不同位置出现的子串算同一个子串,这里巨大的坑点是要把后缀自动机上除起点以外的所有点的sz置为1(不管它是虚拟节点还是真实节点),这一点萌新还没理解...

    然后把所有节点按照len值从小到大排序,然后做一个倒着的转移,每个节点首先能转移出sz个子串,然后加上它后继节点的贡献,可以求出每个节点往后可以转移出多少种子串。

    然后贪心的找。

    对于t=1的情况,和以前一样,求出每个节点所代表的字符串集合在母串中出现了几次(即子树大小)。

    然后把所有节点按照len值从小到大排序,倒着转移。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e6+100;
    int len[maxn],link[maxn],nxt[maxn][26];
    int sz[maxn];
    int tot=1,lst=1;
    string s;
    int n,t,k;
    void sam_extend (char c) {
    	int cur=++tot;
    	len[cur]=len[lst]+1;
    	sz[cur]=1;
    	int p=lst;
    	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;
    	sz[cur]=1;
    }
    vector<int> g[maxn];
    void dfs (int u) {
    	for (int v:g[u]) {
    		dfs(v);
    		sz[u]+=sz[v];
    	}
    } 
    int a[maxn];
    int sum[maxn];
    int cmp (int x,int y) {
    	return len[x]<len[y];
    }
    int main () {
    	cin>>s>>t>>k;
    	for (char i:s) sam_extend(i);
    	for (int i=2;i<=tot;i++) g[link[i]].push_back(i);
    	if (!t)for (int i=2;i<=tot;i++) sz[i]=1;
    	if (t) dfs(1);
    	for (int i=1;i<=tot;i++) a[i]=i;
    	sort(a+1,a+tot+1,cmp);
    	if (t) sz[1]=0;
    	for (int i=tot;i>=1;i--) {
    		sum[a[i]]=sz[a[i]];
    		for (int j=0;j<26;j++) {
    			if (nxt[a[i]][j]) {
    				sum[a[i]]+=sum[nxt[a[i]][j]];
    				//sum[i]表示节点i往后可以转移出多少条不同的子串 
    			}
    		}
    	}
    	if (k>sum[1]) return printf("-1
    "),0;
    	int u=1;
    	while (k>0) {
    		int p=0;
    		while (k>sum[nxt[u][p]]) {
    			k-=sum[nxt[u][p]];
    			p++;
    		}
    		u=nxt[u][p];
    		printf("%c",p+'a');
    		k-=sz[u];
    	}
    }
  • 相关阅读:
    Flink架构、原理与部署测试
    EntityFramework 简单入个门
    Gdb远程调试Linux内核遇到的Bug
    掌握jQuery插件开发
    两分钟实现安全完备的登录模块
    SQL Server 手把手教你使用profile进行性能监控
    Paxos 实现日志复制同步
    作用域是什么
    Consul 服务注册与服务发现
    C语言之预处理
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15017334.html
Copyright © 2020-2023  润新知