zoukankan      html  css  js  c++  java
  • [TJOI2015]弦论

    description

    题面

    求给定字符串的第(k(kle 10^9))大子串。无解输出-1,(nle 5 imes 10^5)
    分不同位置的相同子串算作一个,不同位置的相同子串算作多个两种情况

    solution

    我们首先要建立一个(SAM)...

    由于(SAM)相当于一个放了当前字符串的所有子串的(AC)自动机,
    因此我们可以直接在(SAM)上进行查找

    如果不同位置的相同子串算作一个,那么我们实际上要做的就是查找本质不同的第(k)大子串;
    (sum_i)表示当前查找到第(i)号节点后,从该节点出发能找到能被(SAM)识别的多少子串(包括空串)
    求的时候只要把节点按照(len_i)拍个序,然后按照(SAM)的转移边像树形(DP)处理(sz)一样处理即可

    for(RG int i=1;i<=tot;i++)t[len[i]]++;
    for(RG int i=1;i<=tot;i++)t[i]+=t[i-1];
    for(RG int i=1;i<=tot;i++)a[t[len[i]]--]=i;
    //这里是基数排序
    for(RG int i=1;i<=tot;i++)sum[i]=sz[i]=1;
    
    sz[1]=sum[1]=0;
    for(RG int i=tot;i;i--)
    	for(RG int j=0;j<26;j++)
    		sum[a[i]]+=sum[tr[a[i]][j]];
    

    如果不同位置的相同子串算作多个,那么我们肯定要处理出(endpos_i(right_i))的大小((sz)):

    void extend(int c){
        ...
    	sz[u]=1;
    }
    for(RG int i=1;i<=tot;i++)t[len[i]]++;
    for(RG int i=1;i<=tot;i++)t[i]+=t[i-1];
    for(RG int i=1;i<=tot;i++)a[t[len[i]]--]=i;
    for(RG int i=tot;i;i--)sz[fa[a[i]]]+=sz[a[i]];
    
    sz[1]=sum[1]=0;
    for(RG int i=tot;i;i--)
    	for(RG int j=0;j<26;j++)
    		sum[a[i]]+=sum[tr[a[i]][j]];
    

    然后向上面一样处理出(sum)即可

    code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define FILE "a"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-10;
    const int mod=1e9+7;
    const int N=1000010;
    const dd pi=acos(-1);
    const int inf=2147483647;
    const ll INF=1e18+1;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    il void file(){
    	srand(time(NULL)+rand());
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    }
    
    char s[N];
    int n,b,k,tr[N][26],fa[N],sz[N],len[N],sum[N],a[N],t[N],tot=1,lst=1;
    il void extend(int c){
    	RG int u=++tot,v=lst;lst=u;len[u]=len[v]+1;
    	while(v&&!tr[v][c])tr[v][c]=u,v=fa[v];
    	if(!v)fa[u]=1;
    	else{
    		RG int x=tr[v][c];
    		if(len[x]==len[v]+1)fa[u]=x;
    		else{
    			RG int y=++tot;len[y]=len[v]+1;
    			memcpy(tr[y],tr[x],sizeof(tr[y]));
    			fa[y]=fa[x];fa[x]=fa[u]=y;
    			while(v&&tr[v][c]==x)tr[v][c]=y,v=fa[v];
    		}
    	}
    	sz[u]=1;
    }
    
    il void search(int p,int x,int k){
    	if(sum[x]<k){puts("-1");exit(0);}
    	for(RG int i=0;i<26;i++)
    		if(tr[x][i]){
    			if(k<=sum[tr[x][i]]){
    				s[p]=i+'a';
    				if(k<=sz[tr[x][i]]){
    					s[p+1]=0;
    					printf("%s
    ",s+1);
    					exit(0);
    				}
    				else search(p+1,tr[x][i],k-sz[tr[x][i]]);
    			}
    			else k-=sum[tr[x][i]];
    		}
    }
    
    int main()
    {
    	scanf("%s",s+1);n=strlen(s+1);b=read();k=read();
    	for(RG int i=1;i<=n;i++)extend(s[i]-'a');
    	//Case 1
    	
    	for(RG int i=1;i<=tot;i++)t[len[i]]++;
    	for(RG int i=1;i<=tot;i++)t[i]+=t[i-1];
    	for(RG int i=1;i<=tot;i++)a[t[len[i]]--]=i;
    	for(RG int i=tot;i;i--)sz[fa[a[i]]]+=sz[a[i]];
    	for(RG int i=1;i<=tot;i++)sum[i]=sz[i]=(b?sz[i]:1);
    	sz[1]=sum[1]=0;
    	
    	for(RG int i=tot;i;i--){
    		for(RG int j=0;j<26;j++)
    			sum[a[i]]+=sum[tr[a[i]][j]];
    		//printf("sum[%d]=%d,sz[%d]=%d
    ",a[i],sum[a[i]],a[i],sz[a[i]]);
    	}
    	//Case 2
    	
    	search(1,1,k);
    	//Case 3
    	
    	return 0;
    }
    
    
  • 相关阅读:
    三层架构(我了解并详细分析)
    define a class for a linked list and write a method to delete the nth node.
    无阻塞情况connect生产EINPROGRESS错
    辛星和你解读PHP递归
    Android -- Looper.prepare()和Looper.loop() —深度版
    Canvas翻转方法
    BP神经网络的基本原理
    muduo网络图书馆评测
    HBASE
    MySQL
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9362713.html
Copyright © 2011-2022 走看看