洛谷P2414 [NOI2011]阿狸的打字机(AC自动机)

本文介绍了一种使用AC自动机与树状数组解决字符串匹配问题的方法,通过构建AC自动机的fail树,利用dfs序和树状数组进行序列统计,实现高效查找串B在串A中的出现次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

 

考虑一下,如果串B在串A中出现过,那么A的fail指针必定直接或间接指向B

那么我们可以把fail树建起来,那么就变成B代表的节点的子树里有多少节点属于A

然后这就是一个序列统计问题,直接用dfs序+树状数组可以维护

具体的操作就是,先把每一个点有关的询问给存起来,然后等到在trie树上一遍dfs,当dfs到这个串的结束节点说明所有有关这个串的节点都被遍历到(可以在遍历的时候顺便用树状数组维护序列和),然后对每一个询问查一下子树和即可

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<queue>
  6 #include<algorithm>
  7 using namespace std;
  8 const int N=100005;
  9 int tot=1;
 10 struct node{
 11     int num,type;
 12     node(){}
 13     node(int num,int type):num(num),type(type){}
 14 };
 15 queue<node> q;
 16 int ch[N][26],End[N],word,fa[N],fail[N],dis[N];
 17 inline int insert(int p,int c){
 18     if(ch[p][c]) return ch[p][c];
 19     ch[p][c]=++tot,fa[tot]=p;return tot;
 20 }
 21 inline int back(int p){return fa[p];}
 22 inline void ed(int p){End[p]=++word,dis[word]=p;}
 23 void build(){
 24     for(int i=0;i<26;++i)
 25     if(ch[1][i])
 26     q.push(node(ch[1][i],i)),fail[ch[1][i]]=1;
 27     while(!q.empty()){
 28         node now=q.front();q.pop();
 29         if(fail[now.num]!=1){
 30             int trail=fail[fa[now.num]];
 31             while(true){
 32                 if(ch[trail][now.type]){trail=ch[trail][now.type];break;}
 33                 if(trail==1) break;trail=fail[trail];
 34             }
 35             fail[now.num]=trail;
 36         }
 37         for(int i=0;i<26;++i)
 38         if(ch[now.num][i])
 39         q.push(node(ch[now.num][i],i));
 40     }
 41 }
 42 int ver[N<<1],Next[N<<1],head[N],E=0;
 43 inline void add(int u,int v){
 44     ver[++E]=v,Next[E]=head[u],head[u]=E;
 45 }
 46 int ver1[N],Next1[N],head1[N],edge1[N],E1=0;
 47 inline void add1(int u,int v,int num){
 48     ver1[++E1]=v,Next1[E1]=head1[u],head1[u]=E1,edge1[E1]=num;
 49 }
 50 int c[N<<1];
 51 inline void addd(int x,int y){
 52     for(;x<=tot;x+=x&-x) c[x]+=y;
 53 }
 54 inline int sum(int x){
 55     int res=0;
 56     for(;x;x-=x&-x) res+=c[x];
 57     return res;
 58 }
 59 int dfn[N],sz[N],cnt=0,ans[N];
 60 bool book[N];
 61 void dfsfail(int u){
 62     dfn[u]=++cnt,sz[u]=1,book[u]=true;
 63     for(int i=head[u];i;i=Next[i]){
 64         int v=ver[i];
 65         if(!book[v]) dfsfail(v),sz[u]+=sz[v];
 66     }
 67 }
 68 void dfstrie(int u){
 69     addd(dfn[u],1);
 70     if(End[u]){
 71         for(int i=head1[End[u]];i;i=Next1[i]){
 72             int v=ver1[i],x=dis[v];
 73 //            printf("%d %d %d\n",v,x,edge1[i]);
 74             ans[edge1[i]]=sum(dfn[x]+sz[x]-1)-sum(dfn[x]-1);
 75         }
 76     }
 77     for(int i=0;i<26;++i)
 78     if(ch[u][i]) dfstrie(ch[u][i]);
 79     addd(dfn[u],-1);
 80 }
 81 char s[N];int len,m,st;
 82 int main(){
 83 //    freopen("testdata.in","r",stdin);
 84     scanf("%s",s+1);
 85     len=strlen(s+1);
 86     for(st=1;st<=len;++st)
 87     if(s[st]!='B'&&s[st]!='P') break;
 88     int p=insert(1,s[st]-'a');
 89     for(int i=st+1;i<=len;++i){
 90         if(s[i]=='B') p=back(p);
 91         else if(s[i]=='P') ed(p);
 92         else p=insert(p,s[i]-'a');
 93     }
 94     scanf("%d",&m);
 95     for(int i=1,u,v;i<=m;++i){
 96         scanf("%d%d",&u,&v);
 97         add1(v,u,i);
 98     }
 99     build();
100     for(int i=2;i<=tot;++i)
101     add(fail[i],i),add(i,fail[i]);
102     dfsfail(1),dfstrie(1);
103     for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
104     return 0;
105 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9643024.html

电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格和销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌和年份的电动汽车和插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售和安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商和车型组合,包括纯电动汽车和插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准和速度、价格、产地、自主水平、排放、安全等级、销售和保修。 时间跨度:模型跨度多年(包括传统和即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含不同的、特定于供应商的值(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km和额定值。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值