题目大意

给定\(n\)个字符串和\(k\)
对于每个字符串,输出它有多少个子串至少是\(k\)个字符串的子串(包括自己)

分析

建出广义后缀自动机
至少是\(k\)个字符串的子串就是求子树内不同数个数
考虑怎么统计答案

不要做本质不同子串做傻了
这题是问有多少个子串,子串相同位置不同是可以重复统计的

直接找字符串的每个后缀,它们前缀对应的子串开始位置都是不同的,不会算重
统计的就是每个后缀对应的节点 到跟路径上 有多少合法
dfs预处理一下树上前缀和就好

solution

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int M=200007;inline int rd(){int x=0;bool f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=0;for(;isdigit(c);c=getchar()) x=x*10+c-48;return f?x:-x;
}LL sum[M];
int n,m;
char s[M];
int last,tot;
int stp[M];
int ch[M][26];
int fa[M];
int que[M],ed[M];
int q[M],tq;
int dfn[M],sz[M],tdfn;
int pre[M][20],Mx,dep[M];struct edge{int y,nxt;};
struct vec{int g[M],te;edge e[M];vec(){memset(g,0,sizeof(g));te=0;}void clear(){memset(g,0,sizeof(g));te=0;}inline void push(int x,int y){e[++te].y=y;e[te].nxt=g[x];g[x]=te;}inline int& operator () (int &x){return g[x];}inline edge& operator [] (int &x){return e[x];}
}go;int newnode(int ss){stp[++tot]=ss;return tot;
}int ext(int p,int q,int d){int nq=newnode(stp[p]+1);fa[nq]=fa[q]; fa[q]=nq;memcpy(ch[nq],ch[q],sizeof(ch[q]));for(;p&&ch[p][d]==q;p=fa[p]) ch[p][d]=nq;return nq;
}int sam(int p,int d){int np=ch[p][d];if(np) return (stp[p]+1==stp[np]) ? np : ext(p,np,d);np=newnode(stp[p]+1);for(;p&&!ch[p][d];p=fa[p]) ch[p][d]=np;if(!p) fa[np]=1;else{int q=ch[p][d];fa[np]= (stp[p]+1==stp[q]) ? q : ext(p,q,d);}return np;
}int dfs(int x){dfn[x]=++tdfn;sz[x]=1;int p,y;for(p=go(x);p;p=go[p].nxt){y=go[p].y;dep[y]=dep[x]+1;pre[y][0]=x;dfs(y);sz[x]+=sz[y];}
}bool cmp(int x,int y){return dfn[x]<dfn[y];
}int LCA(int x,int y){if(dep[x]<dep[y]) swap(x,y);for(int t=Mx;t>=0;t--)if(dep[pre[x][t]]>=dep[y]) x=pre[x][t];if(x==y) return x;for(int t=Mx;t>=0;t--)if(pre[x][t]!=pre[y][t]) x=pre[x][t],y=pre[y][t];return pre[x][0];
}int c[M];inline int lb(int x){return x&(-x);}inline int add(int x,int d){for(;x<=tdfn;x+=lb(x)) c[x]+=d;
}inline int get(int x){int res=0;for(;x>0;x-=lb(x)) res+=c[x];return res;
}inline int get(int x,int y){return get(y)-get(x-1);
}void vtree(int l,int r){int i,x,p,y;tq=0;for(i=l;i<=r;i++) q[++tq]=que[i];sort(q+1,q+tq+1,cmp);for(i=1;i<=tq;i++) add(dfn[q[i]],1);for(i=2;i<=tq;i++) add(dfn[LCA(q[i],q[i-1])],-1);
}void gao(int x){int p,y;for(p=go(x);p;p=go[p].nxt){y=go[p].y;if(get(dfn[y],dfn[y]+sz[y]-1)>=m) sum[y]=sum[x]+stp[y]-stp[x];else sum[y]=sum[x];gao(y);}
}int main(){int i,j,p;n=rd(),m=rd();tot=1;for(i=1;i<=n;i++){scanf("%s",s+1);last=1;p=strlen(s+1);for(j=p;j>0;j--){last=sam(last,s[j]-'a');//***que[++tq]=last;}ed[i]=tq;}for(i=2;i<=tot;i++) go.push(fa[i],i);dfs(1);Mx=log2(tot);for(j=1;j<=Mx;j++)for(i=1;i<=tot;i++) pre[i][j]=pre[pre[i][j-1]][j-1];for(i=1;i<=n;i++) vtree(ed[i-1]+1,ed[i]);gao(1);for(i=1;i<=n;i++){LL ans=0;for(j=ed[i-1]+1;j<=ed[i];j++)ans+=sum[que[j]];printf("%lld\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/acha/p/6581283.html

bzoj 3277 串 后缀树+子树不同数个数相关推荐

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

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

  2. BZOJ 3277 串 BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析)

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

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

    题目链接 \(Description\) 给定n个串和K,求每个串中有多少个子串是这n个串中至少K个串的子串. \(Solution\) 同上题,我们可以算出每个节点所代表的串出现在了几个串中:而且我 ...

  4. SPOJ DQUERY D-query(主席树 区间不同数个数)

    题意:问你区间有几个不同的数 思路:主席树nb.我们知道主席树每一个root都存着一棵权值线段树,现在我们在每个root中存位置,也就是01表示这个位置存不存在.然后我们用一个fa[a[i]]表示a[ ...

  5. 【转】从Trie树(字典树)谈到后缀树

    本文第一部分,咱们就来了解这个Trie树,然后自然而然过渡到第二部分.后缀树,接着进入第三部分.详细阐述后缀树的构造方法-Ukkonen. 第一部分.Trie树 1.1.什么是Trie树 Trie树, ...

  6. 后缀自动机构造后缀树

    http://www.elijahqi.win/archives/3945 今天研究一天怎么构造始终想不明白 看到这篇blog之后顿悟 为了帮助其他人避免像蒟蒻我一样 想不明白感到难过 于是随便写一写 ...

  7. 从Trie树(字典树)和后缀树

    从Trie树(字典树)谈到后缀树 转载:http://blog.csdn.net/v_july_v/article/details/6897097#t22 感谢作者,侵删. 引言 常关注本blog的读 ...

  8. NOI数据结构:后缀树

    NOI数据结构:后缀树 后缀树_fanzitao的专栏-CSDN博客_后缀树 后缀树 - sangmado - 博客园 字符串-后缀树和后缀数组详解 字符串-后缀树和后缀数组详解_吴泽龙的博客-CSD ...

  9. 字符串相关处理kmp,前缀数,后缀树,后缀数组,最长回文串,最长重复字串,最长非重复字串

    1. 最长回文串 一般用后缀数组或者后缀树可以解决, 用此方法:http://blog.csdn.net/v_july_v/article/details/6897097 预处理后缀树,使得查询LCA ...

最新文章

  1. 大规模集群中Docker镜像如何分发管理?试试Uber刚开源的Kraken
  2. 31 多线程同步之Lock(互斥锁)
  3. java if else嵌套,减少的 if else 嵌套 可以使用java 8的Consumer
  4. python panda读取csv_python pandas 中文件的读写——read_csv()读取文件
  5. uniapp的目录结构反思与整理 app.vue【base】pages.json【配置】main.json【框架入口文件】
  6. 一些加快 程序运行速度的方法
  7. hibernate 继承映射(二)
  8. 微软官方确认!要在Edge中采用Chromium,还会带到Mac上
  9. 微软编程一小时--微软2014实习生招募编程模拟测试感想
  10. 悟空学Linux专栏----第3篇
  11. 力扣上的代码想在本地编译运行?
  12. 开发中遇到的Mac使用问题
  13. 和cc2500通信时总是读入0F
  14. 形式语言与自动机 下推自动机
  15. Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例
  16. 网线插座接法,网线模块制作及其安装步骤(图解)
  17. 和金融男谈恋爱 vs 和程序员谈恋爱
  18. Jenkins 自动构建之日程表配置
  19. wamp介绍及crossbar.io服务搭建
  20. 【金猿产品展】Smartbi一站式大数据分析平台——一个平台、所有数据、无限可能。...

热门文章

  1. 最吸量的手游ICON设计参考资料
  2. 朱峰谈概念设计(七)创作性绘画教程
  3. Serekh塞拉赫资源包背后的创作过程
  4. ubuntu搭建【python】运行环境
  5. Java的二十三种设计模式(原型模式(Prototype))
  6. linux平台下Tomcat的安装与优化
  7. php_中替换换行符
  8. 数据在计算机中的存储
  9. [转]PHP程序61条面向对象分析设计的经验原则
  10. 趣味编程:C#中Specification模式的实现(参考答案 - 下)