这题就比较有趣了。

首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链)

然后就可以搞了。

关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下)。

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define maxn 600005
struct Query{
int l,r,id;
void print(){printf("Query : %d to %d (id is %d)\n",l,r,id);}
}brr[maxn];
bool cmp(Query a,Query b)
{return a.l==b.l?a.r<b.r:a.l<b.l;}
struct Bit_Tree{
int x[maxn];
void add(int pos,int f,int tot)
{for (;pos<=tot;pos+=(pos&(-pos))) x[pos]+=f;}
int query(int pos)
{int ret=0;for(;pos;pos-=(pos&(-pos)))ret+=x[pos];return ret;}
}BT;
class Suffix_Automata{
public:
int arr[maxn],tot,top;
int last,cnt,n,k;
char s[maxn];
vector <int> v[maxn],vb[maxn];
int h[maxn],to[maxn],ne[maxn],en,in[maxn],out[maxn];
int go[maxn][26],l[maxn],fa[maxn];
void init()
{
last=cnt=1; en=0;
memset(h,-1,sizeof h);
memset(go,0,sizeof go);
}
void add(int x,int id)
{
int p=last,q;
if (q=go[p][x])
{
if (l[q]==l[p]+1) last=q;
else
{
int nq=++cnt;
l[nq]=l[p]+1;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q];
fa[q]=nq;
for(;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
last=nq;
}
}
else
{
int np=++cnt; l[np]=l[p]+1;
for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
if (!p) fa[np]=1;
else
{
q=go[p][x];
if (l[q]==l[p]+1) fa[np]=q;
else
{
int nq=++cnt;
l[nq]=l[p]+1;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
}
}
last=np;
}
v[last].push_back(id);
vb[id].push_back(last);
}
void addedge(int a,int b)
{
to[en]=b;
ne[en]=h[a];
h[a]=en++;
}
void ins(int id)
{
last=1;scanf("%s",s+1);
int len=strlen(s+1);
F(j,1,len) add(s[j]-'a',id);
}
void dfs(int o)
{
in[o]=++tot;
for (int i=0;i<v[o].size();++i) arr[tot++]=v[o][i];
for (int i=h[o];i>=0;i=ne[i]) dfs(to[i]);
out[o]=tot;
++top;brr[top].l=in[o];brr[top].r=out[o];brr[top].id=o;
}
void dfs2(int o)
{
for (int i=h[o];i>=0;i=ne[i])
f[to[i]]+=f[o],dfs2(to[i]);
}
int lst[maxn],nxt[maxn],ans[maxn],f[maxn];
void solve()
{
init();
scanf("%d%d",&n,&k);
F(i,1,n) ins(i);
F(i,1,cnt) addedge(fa[i],i);
dfs(1);
// printf("Arr : ");F(i,1,tot) printf("%d ",arr[i]); printf("\n");
sort(brr+1,brr+top+1,cmp);
// F(i,1,top) brr[i].print();
F(i,1,tot)
{
if (!lst[arr[i]]&&arr[i]) BT.add(i,1,tot);
else nxt[lst[arr[i]]]=i;
lst[arr[i]]=i;
}
// F(i,1,tot) printf("%d ",nxt[i]); printf("\n");
int now=1;
F(i,1,top)
{
while (now<brr[i].l)
{
if (nxt[now]&&arr[nxt[now]]) BT.add(nxt[now],1,tot);
now++;
}
ans[brr[i].id]=BT.query(brr[i].r)-BT.query(brr[i].l-1);
}
// F(i,1,top) printf("[%d] %d\n",i,ans[i]);
F(i,1,top) if (ans[i]>=k) f[i]=l[i]-l[fa[i]]; else f[i]=0;
dfs2(1);
F(i,1,n)
{
ll ans=0;
F(j,0,vb[i].size()-1) ans+=f[vb[i][j]];
printf("%lld",ans);
if (i!=n) printf(" ");
}
}
}sam; int main()
{sam.solve();}

  

BZOJ 3473 字符串 ——广义后缀自动机的更多相关文章

  1. BZOJ 3473: 字符串 [广义后缀自动机]

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 354  Solved: 160[Submit][Status][Discuss] ...

  2. BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)

    标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...

  3. bzoj 3277: 串 & bzoj 3473: 字符串【后缀自动机||后缀数组】

    建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说 ...

  4. BZOJ 3277 串 (广义后缀自动机)

    3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...

  5. 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机

    题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...

  6. BZOJ 2894: 世界线 广义后缀自动机

    Code: #include<bits/stdc++.h> #define maxn 300000 #define ll long long using namespace std; ve ...

  7. bzoj 3926 转换+广义后缀自动机

    思路:重点在于叶子节点只有20个,我们把叶子节点提到根,把20个trie图插入后缀自动机,然后就是算有多少个本质不同的字串. #include<bits/stdc++.h> #define ...

  8. BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)

    Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999.   他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...

  9. BZOJ3473 字符串 广义后缀自动机

    今天主攻了下SAM 好多东西以前都没理解到 对于这道题 我们建一个自动机存所有串 每个穿last从1开始 对于自动机上每个点额外记一个cnt 表示能匹配到这个点的不同串个数 建完对每个串在自动机上匹配 ...

随机推荐

  1. 对于HDMI设备连接状态的监听

    对与最近主要做的是电视机盒子端的开发,其中涉及到设备的状态监听比较繁琐,所以对HDMI的连接状态的监听方法做个记录,方便后续查看. 主要通过两种方式: (1)比较常用的广播监听 注册一个动态广播来获取 ...

  2. SQL server 数据库基础语句 查询语句

    这一章要学习查询语句 我看car这一数据 我们就开始打上 select  *from car 条件修改 update 表名 set 列名1=值1 where 列名2=值2   //当列名2=值2时   ...

  3. Linux SSH无密码login

    一:ssh原理图为: 1.就是为了让两个linux机器之间使用ssh不需要用户名和密码.采用了数字签名RSA或者DSA来完成这个操作 2.模型分析 假设 A (192.168.20.59)为客户机器, ...

  4. An internal error occurred during: "Map/Reduce location status updater". java.lang.NullPointerException

    eclipse配置hadoop 2.6 服务器做的虚拟机,因为window是的hadoop会出现意想不到的错误,因为,我做了ubuntu的虚拟机供我使用 在虚拟机中进行映射设置 在eclipse中dr ...

  5. 在web应用中使用日志

    Log4J是Jakarta下的一个开源代码的子项目,用Log4J,我们可以使用定制的格式,把调试信息和日志信息输出到一个或多个需要的地方. 在Web应用中一般使用一个专门的Servlet来完成Log4 ...

  6. webpack devserver的说明

    一般我们在项目中 如果用webpack的话,基本都会用到webpack-dev-server,配置大致如下: devServer={ contentBase: basePath, historyApi ...

  7. JdbcTemplate类对sql的操作使用

    <!--方式一: dbcp 数据源配置,在测试环境使用单连接 --> <bean id="dataSource" class="org.apache.c ...

  8. SpringBoot整合升级Spring Security 报错 【The request was rejected because the URL was not normalized】

    前言 最近LZ给项目框架升级, 从Spring1.x升级到Spring2.x, 在这里就不多赘述两个版本之间的区别以及升级的原因. 关于升级过程中踩的坑,在其他博文中会做比较详细的记录,以便给读者参考 ...

  9. excel数据导入到数据库

    package test; import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundExceptio ...

  10. ios 检查内存泄露

    简介 在IPhone程式开发中,记忆体泄漏(内存泄漏)是个很容易发生的情况,因为IPhone必须自行作记忆体管理.现在的开发者,大多习惯用的.NET或Java的等有垃圾回收机制的开发语言来作开发,因此 ...