SPOJ SUBLEX: Lexicographical Substring Search 题解

本文介绍了一个基于Suffix Array Matching (SAM)的数据结构实现,用于解决字符串中子串的字典序排列问题。通过构建SAM,可以高效地找出字符串所有子串,并按字典序排序后找到第K个子串。

Description

Little Daniel loves to play with strings! He always finds different ways to have fun with strings! Knowing that, his friend Kinan decided to test his skills so he gave him a string S and asked him Q questions of the form:

If all distinct substrings of string S were sorted lexicographically, which one will be the K-th smallest?

After knowing the huge number of questions Kinan will ask, Daniel figured out that he can’t do this alone. Daniel, of course, knows your exceptional programming skills, so he asked you to write him a program which given S will answer Kinan’s questions.

Example:
S = “aaa” (without quotes)
substrings of S are “a” , “a” , “a” , “aa” , “aa” , “aaa”. The sorted list of substrings will be: “a”, “aa”, “aaa”.

Input

In the first line there is Kinan’s string S (with length no more than 90000 characters). It contains only small letters of English alphabet. The second line contains a single integer Q (Q <= 500) , the number of questions Daniel will be asked. In the next Q lines a single integer K is given (0 < K < 2^31).

Output

Output consists of Q lines, the i-th contains a string which is the answer to the i-th asked question.

Sample Input

aaa
2
2
3

Sample Output

aa
aaa

Edited

Some input file contains garbage at the end. Do not process them.


我们可以联想到字符串的所有子串都会对应到SAM的一个状态
首先对原串建SAM,然后考虑对每个点,计算从他出发还能走到多少个子串
这里我刚开始写sb了,要注意一个点的贡献不是maxi-mini,因为我已经固定了前面的路径,这部分会算多,联想把S的任意子串扔进SAM,一定会沿着转移边走到一个节点,所以每个点的贡献就是1,直接数size就好了
然后从SAM的根节点出发,每次按照边的字典序访问,如果当前sz小于k就换下一条边,否则沿着这条边走下去,把这条边对应的字符加到答案里
写的有点混乱,贴代码

#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define LB long double
#define ull unsigned long long
#define x first
#define y second
#define pb push_back
#define pf push_front
#define mp make_pair
#define Pair pair<int,int>
#define pLL pair<LL,LL>
#define pii pair<double,double>

const int INF=2e9;
const LL LINf=2e16;
const int magic=348;
const int MOD=998244353;
const double eps=1e-10;
const double pi=acos(-1);

inline int getint()
{
    bool f;char ch;int res;
    while (!isdigit(ch=getchar()) && ch!='-') {}
    if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
    while (isdigit(ch=getchar())) res=res*10+ch-'0';
    return f?res:-res;
}

const int MAXN=1e5;

char s[MAXN+48];int len;

namespace SAM
{
    int nxt[MAXN*2][30],par[MAXN*2],maxn[MAXN*2],minn[MAXN*2],tot;
    int root,last;
    inline void init() {root=last=++tot;}
    inline void insert(char ch)
    {
        int p=last,np=++tot,w=ch-'a'+1;maxn[np]=maxn[p]+1;
        while (p && !nxt[p][w]) nxt[p][w]=np,p=par[p];
        if (!p)
            par[np]=root;
        else
        {
            int q=nxt[p][w];
            if (maxn[q]==maxn[p]+1)
                par[np]=q;
            else
            {
                int nq=++tot;maxn[nq]=maxn[p]+1;
                memcpy(nxt[nq]+1,nxt[q]+1,26*sizeof(int));
                par[nq]=par[q];par[q]=par[np]=nq;
                while (p && nxt[p][w]==q) nxt[p][w]=nq,p=par[p];
            }
        }
        last=np;
    }
}

using namespace SAM;

int sz[MAXN*2],sm[MAXN*2];

inline int dfs(int cur)
{
    if (sz[cur]!=-1) return sz[cur];
    if (cur!=1) sz[cur]=1;
    for (register int i=1;i<=26;i++)
        if (nxt[cur][i]) sz[cur]+=dfs(nxt[cur][i]);
    return sz[cur];
}

string ans;
inline void getans(int cur,int k)
{
    int i;if (cur!=1) k--;
    if (!k) return;
    for (i=1;i<=26;i++)
        if (nxt[cur][i])
        {
            if (sz[nxt[cur][i]]>=k) {ans+=string(1,'a'+i-1);getans(nxt[cur][i],k);return;}
            k-=sz[nxt[cur][i]];
        }
}

int main ()
{
    int i;scanf("%s",s+1);len=strlen(s+1);
    init();for (i=1;i<=len;i++) insert(s[i]);
    for (i=2;i<=tot;i++) minn[i]=maxn[par[i]]+1;
    memset(sz,-1,sizeof(sz));
    dfs(1);int q=getint(),k;
    while (q--)
    {
        k=getint();ans="";
        getans(1,k);cout<<ans<<endl;
    }
    return 0;
}
【SCI一区复现】基于配电网韧性提升的应急移动电源预配置和动态调度(下)—MPS动态调度(Matlab代码实现)内容概要:本文档围绕“基于配电网韧性提升的应急移动电源预配置和动态调度”主题,重点介绍MPS(Mobile Power Sources)动态调度的Matlab代码实现,是SCI一区论文复现的技术资料。内容涵盖在灾害或故障等极端场景下,如何通过优化算法对应急移动电源进行科学调度,以提升配电网在突发事件中的恢复能力与供电可靠性。文档强调采用先进的智能优化算法进行建模求解,并结合IEEE标准测试系统(如IEEE33节点)进行仿真验证,具有较强的学术前沿性和工程应用价值。; 适合人群:具备电力系统基础知识和Matlab编程能力,从事电力系统优化、配电网韧性、应急电源调度等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于复现高水平期刊(SCI一区、IEEE顶刊)中关于配电网韧性与移动电源调度的研究成果;②支撑科研项目中的模型构建与算法开发,提升配电网在故障后的快速恢复能力;③为电力系统应急调度策略提供仿真工具与技术参考。; 阅读建议:建议结合前篇“MPS预配置”内容系统学习,重点关注动态调度模型的数学建模、目标函数设计与Matlab代码实现细节,建议配合YALMIP等优化工具包进行仿真实验,并参考文中提供的网盘资源获取完整代码与数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值