正题

题目链接:https://ac.nowcoder.com/acm/contest/72/F


题目大意

\(n\)个字符串,包括小写字母和\(\#\)。其中\(\#\)可以替换为任意字符串。求有多少对字符串可能相同。

保证每个字符串至少有一个\(\#\)。

\(2\leq n\leq 500000,\sum_{i=1}^n |s_i|\leq 10^6\)


解题思路

因为可以替换为任意字符串,所以只需要考虑第一个\(\#\)前和最后一个\(\#\)后的部分。

在仔细考虑一下,这个字符串分成前后的两个部分\(s,t\)。数对\((x,y)\)满足条件当且仅当\(s_x\)是\(s_y\)的前缀,或者\(s_y\)是\(s_x\)的前缀,且\(t_x\)是\(t_y\)的后缀,或者\(t_y\)是\(t_x\)的后缀。

放到两棵\(Trie\)树上就是都有祖先关系就好了,直接跑第一棵上,然后用两个树状数组在第二棵树上维护就好了。

时间复杂度\(O(m\log m)\)


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. #define lowbit(x) (x&-x)
  6. using namespace std;
  7. const int N=1e6+10;
  8. int n,cnt,pos[N],dfn[N],ed[N];
  9. long long ans;char s[N];
  10. vector<int> G[N];
  11. struct TreeBinary{
  12. int t[N];
  13. void Change(int x,int val){
  14. while(x<=cnt){
  15. t[x]+=val;
  16. x+=lowbit(x);
  17. }
  18. return;
  19. }
  20. int Ask(int x){
  21. int ans=0;
  22. while(x){
  23. ans+=t[x];
  24. x-=lowbit(x);
  25. }
  26. return ans;
  27. }
  28. }Bf,Bs;
  29. struct Trie{
  30. int t[N][26],m=1;
  31. int Insert(char *s,int n){
  32. int x=1;
  33. for(int i=1;i<=n;i++){
  34. if(s[i]=='#')break;
  35. int c=s[i]-'a';
  36. if(!t[x][c])t[x][c]=++m;
  37. x=t[x][c];
  38. }
  39. return x;
  40. }
  41. }Tp,Ts;
  42. void dfs(int x){
  43. dfn[x]=++cnt;
  44. for(int i=0;i<26;i++)
  45. if(Ts.t[x][i])
  46. dfs(Ts.t[x][i]);
  47. ed[x]=cnt;
  48. }
  49. void work(int x){
  50. for(int i=0;i<G[x].size();i++){
  51. int p=G[x][i];ans+=Bf.Ask(dfn[pos[p]]);
  52. Bf.Change(dfn[pos[p]],1);Bf.Change(ed[pos[p]]+1,-1);
  53. ans+=Bs.Ask(ed[pos[p]])-Bs.Ask(dfn[pos[p]]);
  54. Bs.Change(dfn[pos[p]],1);
  55. }
  56. for(int i=0;i<26;i++)
  57. if(Tp.t[x][i])
  58. work(Tp.t[x][i]);
  59. for(int i=0;i<G[x].size();i++){
  60. int p=G[x][i];Bs.Change(dfn[pos[p]],-1);
  61. Bf.Change(dfn[pos[p]],-1);Bf.Change(ed[pos[p]]+1,1);
  62. }
  63. }
  64. int main()
  65. {
  66. scanf("%d",&n);
  67. for(int i=1;i<=n;i++){
  68. scanf("%s",s+1);
  69. int l=strlen(s+1);
  70. int x=Tp.Insert(s,l);
  71. G[x].push_back(i);
  72. reverse(s+1,s+1+l);
  73. pos[i]=Ts.Insert(s,l);
  74. }
  75. dfs(1);
  76. work(1);
  77. printf("%lld\n",ans);
  78. return 0;
  79. }

Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】的更多相关文章

  1. 【bzoj4548】小奇的糖果 STL-set+树状数组

    题目描述 平面上有n个点,每个点有一种颜色.对于某一条线段,选择所有其上方或下方的点.求:在不包含所有颜色的点的前提下,选择的点数最多是多少.(本题中如果存在某颜色没有相应的点,那么选择任何线段都不算 ...

  2. wannafly 挑战赛10 小H和游戏

    题解: 先利用dfs找出各个节点之间的关系.然后利用一个sum[i][j] 数组  sum[i][0] 表示i这个节点收到影响的次数 sum[i][1]表示i这个节点的儿子们收到影响的次数 sum[i ...

  3. wannafly 挑战赛10 小H和密码

    题意:中文题就不解释了 题解: dp[i][j]表示前i 个轮盘 和一个字符串前j 个字符的匹配情况 ,具体的状态转移解释见代码 #include <cstdio> #include &l ...

  4. 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)

    传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...

  5. H - 逆序数(树状数组)

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...

  6. 算法笔记求序列A每个元素左边比它小的数的个数(树状数组和离散化)

    #include <iostream> #include <algorithm> #include <cstring> using namespace std ; ...

  7. 牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)

    牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) 链接:https://ac.nowcoder.com/acm/problem/15706 现在需要您来帮忙维护这个名册, ...

  8. 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治

    LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...

  9. hdu 4217 Data Structure? 树状数组求第K小

    Data Structure? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

随机推荐

  1. struts2拦截action多种方法

    按照教程写的,运行的时候显示There is no Action mapped for namespace [/] and action name [login!method1] associated ...

  2. 求证:-1/2 <= {2x} - {x} < 1/2

    证:由 x = [x] + {x},知2x = 2[x] + 2{x}. 1.若{x}落在[0,1/2),则2{x} < 1,于是有{2x} = 2{x},此时 {2x} - {x} = {x} ...

  3. tomcat漏洞总结

    描述 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.由 ...

  4. Jenkins 使用PowerShell插件部署Net5项目

    Jenkins安装 PowerShell plugin 插件 新建自由项目 拖到 构建 处,添加 PowerShell 构建 贴入下方脚本即可 # 变量 $ProjectPath = "E: ...

  5. Docker下制作一个容器镜像

    操作过程描述: (1)先基于centos的镜像启动一个centos容器 (2)在这个容器中安装nginx (3)然后把这个已经安装了nginx的容器制作成一个docker的镜像 操作:docker c ...

  6. app自动化定位:UIautomation的用法

    UIautomation定位的优点: 速度比xpath定位快,UIautomation是Android的工作引擎 缺点: 没有idea提示 UIautomation使用方法: AndroidDrive ...

  7. Cobar源码分析之AST

    本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star. 背景 Cobar Cobar是阿里开源的数据库中间件,关于它的介绍这里不再赘述,可以参考之前的 ...

  8. C# 反射 + Quartz,实现流程处理

    场景: 前不久,公司里项目经理要求我实现流程处理,比如,用户可以定义一个定时任务,每周一查看报表.定时任务很简单,用Quartz可以实现,但是用户自己选择报表就比较麻烦,因为系统的不同模块的生成报表的 ...

  9. 【第三篇】- Git 工作流程之Spring Cloud直播商城 b2b2c电子商务技术总结

    Git 工作流程 本章节我们将为大家介绍 Git 的工作流程. 一般工作流程如下: 克隆 Git 资源作为工作目录. 在克隆的资源上添加或修改文件. 如果其他人修改了,你可以更新资源. 在提交前查看修 ...

  10. C语言学习笔记---3.字符串格式化输入输出

    1.C语言字符串 字符串(character string)是一个或多个字符的序列,例如:"Zing went the strings of my heart!" C语言没有专门用 ...