bzoj3998 [TJOI2015]弦论 后缀自动机

本文探讨了经典的求K小子串问题,通过定义right集合来理解不同子串个数,并介绍了一种基于DAG的数据结构解决方案。利用主席树的思想进行遍历,实现高效查找第K小子串。

经典的求k小子串的问题。
根据right集合的定义,如果是相同子串不同位置算作一个,那每一个right集合对应的左右区间长度的大小就是这个right集合所包含的不同子串个数。
但是知道了这个并不代表我们可以直接求出来= =因为你并不知道k小是right集合中的哪一个,也就是说你没有办法准确的用尽量小的复杂度去把这个K小的子串拿出来,所以我们只能在dag上搞事情。。

设sum[i]表示以i为根时子树不同的子串个数。
那么有f[i]=sigma(f[son])+num[i]
num[i]表示以i为根时i这个节点对f的贡献。
那么明显当不算重复时num[i]=1否则num[i]就是i这个节点伸出的边数。
然后dfs一遍像主席树一样求个k大就好了。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e6+5;
typedef long long ll;
int cnt,tot,n,m,mx[N];
char s[N];
int ch[N][30],fa[N];
int f[N],b[N],last,c[N],sum[N];
int T,k;
void ins(int x)
{
    int p,q,np,nq;
    p=last;last=np=++cnt;mx[np]=mx[p]+1;f[np]=1;
    for (;!ch[p][x]&&p;p=fa[p]) ch[p][x]=np;
    if (!p) fa[np]=1;
    else
    {
        q=ch[p][x];
        if (mx[q]==mx[p]+1) fa[np]=q;
        else
        {
            nq=++cnt;mx[nq]=mx[p]+1;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            for (;ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
        }
    }
}
void pre()
{
    for (int i=1;i<=cnt;i++) b[mx[i]]++;
    for (int i=1;i<=n;i++) b[i]+=b[i-1];
    for (int i=1;i<=cnt;i++) c[b[mx[i]]--]=i;
    for (int i=cnt;i>=1;i--)
    {
        if (T==1) f[fa[c[i]]]+=f[c[i]];
        else f[c[i]]=1;
    }
    f[1]=0;
    for (int i=cnt;i>=1;i--)
    {
        int t=c[i];sum[t]=f[t];
        for (int j=0;j<26;j++)
            sum[t]+=sum[ch[t][j]];
    }
}
inline void solve(int x,int k)
{
    if (f[x]>=k)return;
    k-=f[x];
    fo(i,0,25)
    if (ch[x][i])
    {
        int t=ch[x][i];
        if (sum[t]>=k)
        {
            putchar(i+'a');
            solve(ch[x][i],k);
            return;
        }
        else k-=sum[t];
    }
}
int main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    cnt=last=1;
    fo(i,1,n)ins(s[i]-'a');
    scanf("%d%d",&T,&k);
    pre();
    if (k>sum[1])printf("-1");
    else solve(1,k);
    return 0;
}
一、数据采集层:多源人脸数据获取 该层负责从不同设备 / 渠道采集人脸原始数据,为后续模型训练与识别提供基础样本,核心功能包括: 1. 多设备适配采集 实时摄像头采集: 调用计算机内置摄像头(或外接 USB 摄像头),通过OpenCV的VideoCapture接口实时捕获视频流,支持手动触发 “拍照”(按指定快捷键如Space)或自动定时采集(如每 2 秒采集 1 张),采集时自动框选人脸区域(通过Haar级联分类器初步定位),确保样本聚焦人脸。 支持采集参数配置:可设置采集分辨率(如 640×480、1280×720)、图像格式(JPG/PNG)、单用户采集数量(如默认采集 20 张,确保样本多样性),采集过程中实时显示 “已采集数量 / 目标数量”,避免样本不足。 本地图像 / 视频导入: 支持批量导入本地人脸图像文件(支持 JPG、PNG、BMP 格式),自动过滤非图像文件;导入视频文件(MP4、AVI 格式)时,可按 “固定帧间隔”(如每 10 帧提取 1 张图像)或 “手动选择帧” 提取人脸样本,适用于无实时摄像头场景。 数据集对接: 支持接入公开人脸数据集(如 LFW、ORL),通过预设脚本自动读取数据集目录结构(按 “用户 ID - 样本图像” 分类),快速构建训练样本库,无需手动采集,降低系统开发与测试成本。 2. 采集过程辅助功能 人脸有效性校验:采集时通过OpenCV的Haar级联分类器(或MTCNN轻量级模型)实时检测图像中是否包含人脸,若未检测到人脸(如遮挡、侧脸角度过大),则弹窗提示 “未识别到人脸,请调整姿态”,避免无效样本存入。 样本标签管理:采集时需为每个样本绑定 “用户标签”(如姓名、ID 号),支持手动输入标签或从 Excel 名单批量导入标签(按 “标签 - 采集数量” 对应),采集完成后自动按 “标签 - 序号” 命名文件(如 “张三
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值