洛谷P2414 - [NOI2011]阿狸的打字机

本文详细解析了阿狸的打字机问题的高效算法实现,通过构建Trie树与fail树,利用树状数组进行区间查询,解决字符串集合中的匹配次数问题。时间复杂度达到O(nlogn+mlogn)。

Portal

Description

首先给出一个只包含小写字母和'B'、'P'的操作序列\(s_0(|s_0|\leq10^5)\)。初始时我们有一个空串\(t\),依次按\(s_0\)的每一位进行操作:

  • 如果是小写字母,则在\(t\)后面加入这个小写字母;
  • 如果是'B',则删除\(t\)的最后一位;
  • 如果是'P',则复制t到集合\(S\)中。

操作结束后,集合中有\(n(n\leq10^5)\)个字符串,将它们按加入集合的顺序标号为\(1..n\)。接下来\(m(m\leq10^5)\)次询问,每次询问串\(x\)在串\(y\)中出现了几次。

Solution

首先根据\(s_0\)我们可以方便的建出一棵Trie树并建立fail指针,记录代表串\(x\)的节点为\(end[x]\)。然后我们就得到了一个fail树:
1339270-20180406103714507-574495801.png
一个节点在fail树上的祖先就是它的一个后缀,子树就是以该节点作为后缀的串。那么询问就相当于“求\(end[x]\)的子树中,有多少个点在\(root\)\(end[y]\)的路径上”。
我们求出fail树的DFS序,然后将询问按\(y\)排序。用树状数组维护每个点是否被标记,当\(y\)转移到\(y+1\)时,按照建立Trie树的方法转移。求\(end[x]\)的子树中有多少个被标记的点就相当于求DFS序的区间和。

时间复杂度\(O(nlogn+mlogn)\)

Code

//[NOI2011]阿狸的打字机
#include <algorithm>
#include <cstdio>
using std::sort;
int const N=1e5+10;
int n; char s0[N];
struct query{int id,x,y,ans;} q[N];
bool cmpY(query x,query y) {return x.y<y.y;}
bool cmpID(query x,query y) {return x.id<y.id;}
int rt,ndCnt,fa[N],ch[N][26],fail[N]; int end[N];
int Q[N],op,cl;
int edCnt,h[N];
struct edge{int v,nxt;} ed[N];
void edAdd(int u,int v)
{
    fail[v]=u;
    edCnt++; ed[edCnt].v=v,ed[edCnt].nxt=h[u],h[u]=edCnt;
}
void bldFail()
{
    for(int i=0;i<26;i++) ch[0][i]=rt;
    Q[++cl]=rt;
    while(op<cl)
    {
        int p=Q[++op];
        for(int i=0;i<26;i++)
        {
            int q=ch[p][i];
            if(!q) ch[p][i]=ch[fail[p]][i];
            else edAdd(ch[fail[p]][i],q),Q[++cl]=q;
        }
    }
}
int dfCnt,fr[N],to[N];
void dfs(int u)
{
    dfCnt++; fr[u]=dfCnt;
    for(int i=h[u];i;i=ed[i].nxt) dfs(ed[i].v);
    to[u]=dfCnt;
}
int tr[N];
void add(int x,int v) {while(x<=ndCnt) tr[x]+=v,x+=x&(-x);}
int sum(int x) {int r=0; while(x) r+=tr[x],x-=x&(-x); return r;}
int main()
{
    scanf("%s",s0+1);
    rt=++ndCnt;
    for(int i=1,p=rt;s0[i];i++)
    {
        int x=s0[i]-'a';
        if(s0[i]=='B') p=fa[p];
        else if(s0[i]=='P') end[++n]=p;
        else {if(!ch[p][x]) fa[ch[p][x]=++ndCnt]=p; p=ch[p][x];}
    }
    bldFail(); for(int i=1;i<=ndCnt;i++) if(!fr[i]) dfs(i);
    int m; scanf("%d",&m);
    for(int i=1;i<=m;i++) scanf("%d%d",&q[i].x,&q[i].y),q[i].id=i;
    sort(q+1,q+m+1,cmpY);
    int now=0,p=rt;
    for(int i=0,owo=1,no;owo<=m;owo++)
    {
        int x=q[owo].x,y=q[owo].y;
        while(now<y)
        {
            i++;
            if(s0[i]=='B') add(fr[p],-1),p=fa[p];
            else if(s0[i]=='P') now++;
            else p=ch[p][s0[i]-'a'],add(fr[p],1);
        }
        q[owo].ans=sum(to[end[x]])-sum(fr[end[x]]-1);
    }
    sort(q+1,q+m+1,cmpID);
    for(int i=1;i<=m;i++) printf("%d\n",q[i].ans);
    return 0;
}

P.S.

双倍经验BZOJ2434

转载于:https://www.cnblogs.com/VisJiao/p/LgP2414.html

【RIS 辅助的 THz 混合场波束斜视下的信道估计与定位】在混合场波束斜视效应下,利用太赫兹超大可重构智能表面感知用户信道与位置(Matlab代码实现)内容概要:本文围绕“IS 辅助的 THz 混合场波束斜视下的信道估计与定位”展开,重点研究在太赫兹(THz)通信系统中,由于混合近场与远场共存导致的波束斜视效应下,如何利用超大可重构智能表面(RIS)实现对用户信道状态信息和位置的联合感知与精确估计。文中提出了一种基于RIS调控的信道参数估计算法,通过优化RIS相移矩阵提升信道分辨率,并结合信号到达角(AoA)、到达时间(ToA)等信息实现高精度定位。该方法在Matlab平台上进行了仿真验证,复现了SCI一区论文的核心成果,展示了其在下一代高频通信系统中的应用潜力。; 适合人群:具备通信工程、信号处理或电子信息相关背景,熟悉Matlab仿真,从事太赫兹通信、智能反射面或无线定位方向研究的研究生、科研人员及工程师。; 使用场景及目标:① 理解太赫兹通信中混合场域波束斜视问题的成因与影响;② 掌握基于RIS的信道估计与用户定位联合实现的技术路径;③ 学习并复现高水平SCI论文中的算法设计与仿真方法,支撑学术研究或工程原型开发; 阅读建议:此资源以Matlab代码实现为核心,强调理论与实践结合,建议读者在理解波束成形、信道建模和参数估计算法的基础上,动手运行和调试代码,深入掌握RIS在高频通信感知一体化中的关键技术细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值