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

    题意

    第一问有一个经典做法:学习笔记

    对于第二问,其实就是对于一个状态的所有串,第一问看成一个,第二问看成多个。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5*1e5+10;
    int n,type,m,tot,last,cnt;
    int head[maxn<<1],in[maxn<<1],size[maxn<<1];
    ll f[maxn<<1];
    char s[maxn];
    struct edge{int to,nxt;}e[maxn<<2];
    struct Sam
    {
    	int fa,len;
    	int ch[26];
    }sam[maxn<<1];
    inline void add(int u,int v)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    	in[v]++;
    }
    inline void sam_init(){sam[0].fa=-1,sam[0].len=0;last=0;}
    inline void sam_add(int c)
    {
    	int now=++tot;sam[now].len=sam[last].len+1;size[now]=1;
    	int p=last;
    	while(~p&&!sam[p].ch[c])sam[p].ch[c]=now,p=sam[p].fa;
    	if(p==-1){sam[now].fa=0;last=now;return;}
    	int q=sam[p].ch[c];
    	if(sam[q].len==sam[p].len+1)sam[now].fa=q;
    	else
    	{
    		int nowq=++tot;
    		sam[nowq].len=sam[p].len+1;
    		memcpy(sam[nowq].ch,sam[q].ch,sizeof(sam[q].ch));
    		sam[nowq].fa=sam[q].fa;sam[q].fa=sam[now].fa=nowq;
    		while(~p&&sam[p].ch[c]==q)sam[p].ch[c]=nowq,p=sam[p].fa;
    	}
    	last=now;
    }
    void dfs(int x)
    {
    	for(int i=head[x];i;i=e[i].nxt)
    		dfs(e[i].to),size[x]+=size[e[i].to];
    }
    inline void work(int op)
    {
    	if(op)
    	{
    		for(int i=1;i<=tot;i++)add(sam[i].fa,i);
    		dfs(0);
    	}
    	memset(head,0,sizeof(head));
    	memset(in,0,sizeof(in));
    	cnt=0;
    	for(int i=0;i<=tot;i++)
    		for(int j=0;j<26;j++)
    			if(sam[i].ch[j])add(sam[i].ch[j],i);
    	queue<int>q;
    	for(int i=0;i<=tot;i++)if(!in[i])q.push(i);
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		f[x]=!op?1:size[x];
    		//cerr<<f[x]<<endl;
    		for(int i=0;i<26;i++)if(sam[x].ch[i])f[x]+=f[sam[x].ch[i]];
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			int y=e[i].to;
    			if(!(--in[y]))q.push(y);
    		}
    	}
    	f[0]--;
    	//cerr<<f[0]<<endl;
    }
    int main()
    {
    	scanf("%s%d%d",s+1,&type,&m);n=strlen(s+1);
    	sam_init();
    	for(int i=1;i<=n;i++)sam_add(s[i]-'a');
    	work(type);
    	if(m>f[0]){puts("-1");return 0;}
    	int now=0;
    	while(m)
    	{
    		for(int i=0;i<26;i++)
    		{
    			if(!sam[now].ch[i])continue;
    			if(f[sam[now].ch[i]]<m)m-=f[sam[now].ch[i]];
    			else 
    			{
    				m-=!type?1:size[sam[now].ch[i]];now=sam[now].ch[i];
    				putchar(i+'a');break;
    			}
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    validFrom不通过submit按钮来触发表单验证
    微信小程序组件开发
    css3 单行文字溢出,多行文字溢出
    表格布局
    对象设置默认属性
    按钮样式
    判断一个json是否为空
    vue高仿饿了么(三)
    Win10 用IE打开网址默认跳转到Edge如何解决?
    VMware虚拟机安装Win11正式版
  • 原文地址:https://www.cnblogs.com/nofind/p/12047551.html
Copyright © 2011-2022 走看看