码迷,mamicode.com
首页 > 其他好文 > 详细

补题计划

时间:2019-08-17 21:52:46      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:one   sizeof   scanf   hide   stdin   lap   位置   show   +=   

[TJOI2015]弦论(sam)

首先建出当前串s的sam。然后分t=1或者0两种情况讨论。

当t=1时,位置不同的相同字符串算不同。

设开头为某一个x对应的字符串的子串个数是$f[x]$,节点x对应的字符串在整个字符串中出现了$s[x]$次。我们可以通过dfs算法在$parent$树上跑算出$f$和$s$。

我们为了查询字典序,需要从起始节点开始跑自动机。设当前节点为x,代表字符串是s,然后由字典序小到大枚举x后面添加的字符c。如果现在以x+c为开头对应的字符串数量比较小,那么把k减去对应的f。否则,x转移到s+c所对应的节点。

注意每次x转移后也要减去$s[x]$。否则由于没有算上x的贡献,会导致答案错误。

技术图片
#include<bits/stdc++.h>
#define mn 1000005
using namespace std;
char str[mn];long long ans;
int a,k;
    int fa[mn],t[mn][26],len[mn],la,ct,v[mn],h[mn],nxt[mn],ec,s[mn],f[mn];
    void add(int c){
        int cur=++ct,p=la;len[cur]=len[la]+1;s[cur]=1;la=cur;
        for(;p&&!t[p][c];p=fa[p])t[p][c]=cur;
        if(!p){fa[cur]=1;}
        else{
            int q=t[p][c];if(len[p]+1==len[q]){fa[cur]=q;}
            else{
                int cl=++ct;len[cl]=len[p]+1;memcpy(t[cl],t[q],sizeof(t[cl]));
                fa[cl]=fa[q];fa[cur]=fa[q]=cl;
                for(;t[p][c]==q;p=fa[p])t[p][c]=cl;
            }
        }
    }
    void init(){ct=ec=la=1;}
    void adj(int x,int y){v[++ec]=y;nxt[ec]=h[x];h[x]=ec;}
    void bd(){for(int i=2;i<=ct;i++)adj(fa[i],i);}
    int g1(int x){
        for(int i=h[x];i;i=nxt[i])
            s[x]+=g1(v[i]);
        return s[x];
    }
    int g2(int x){
        if(f[x])return f[x];
        if(a)f[x]=s[x];
        else f[x]=1;
        for(int i=0;i<26;i++)
            if(t[x][i])f[x]+=g2(t[x][i]);
        return f[x];
    }
int main(){
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
    scanf("%s%d%d",str+1,&a,&k);init();
    for(int i=1;str[i];i++)add(str[i]-a);
    bd();g1(1);g2(1);
    int x=1;
    while(k>0){
        for(int i=0;i<26;i++){
            int v=t[x][i];
            if(k>f[v])k-=f[v];
            else{
                x=v;
                if(!a)k--;
                else k-=s[v];
                printf("%c",i+a);
                break;
            }
        }
    }
}
View Code

 

补题计划

标签:one   sizeof   scanf   hide   stdin   lap   位置   show   +=   

原文地址:https://www.cnblogs.com/rilisoft/p/11370460.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!