Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】
正题
题目链接: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
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define lowbit(x) (x&-x)
using namespace std;
const int N=1e6+10;
int n,cnt,pos[N],dfn[N],ed[N];
long long ans;char s[N];
vector<int> G[N];
struct TreeBinary{
int t[N];
void Change(int x,int val){
while(x<=cnt){
t[x]+=val;
x+=lowbit(x);
}
return;
}
int Ask(int x){
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
}Bf,Bs;
struct Trie{
int t[N][26],m=1;
int Insert(char *s,int n){
int x=1;
for(int i=1;i<=n;i++){
if(s[i]=='#')break;
int c=s[i]-'a';
if(!t[x][c])t[x][c]=++m;
x=t[x][c];
}
return x;
}
}Tp,Ts;
void dfs(int x){
dfn[x]=++cnt;
for(int i=0;i<26;i++)
if(Ts.t[x][i])
dfs(Ts.t[x][i]);
ed[x]=cnt;
}
void work(int x){
for(int i=0;i<G[x].size();i++){
int p=G[x][i];ans+=Bf.Ask(dfn[pos[p]]);
Bf.Change(dfn[pos[p]],1);Bf.Change(ed[pos[p]]+1,-1);
ans+=Bs.Ask(ed[pos[p]])-Bs.Ask(dfn[pos[p]]);
Bs.Change(dfn[pos[p]],1);
}
for(int i=0;i<26;i++)
if(Tp.t[x][i])
work(Tp.t[x][i]);
for(int i=0;i<G[x].size();i++){
int p=G[x][i];Bs.Change(dfn[pos[p]],-1);
Bf.Change(dfn[pos[p]],-1);Bf.Change(ed[pos[p]]+1,1);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s+1);
int l=strlen(s+1);
int x=Tp.Insert(s,l);
G[x].push_back(i);
reverse(s+1,s+1+l);
pos[i]=Ts.Insert(s,l);
}
dfs(1);
work(1);
printf("%lld\n",ans);
return 0;
}
Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】的更多相关文章
- 【bzoj4548】小奇的糖果 STL-set+树状数组
题目描述 平面上有n个点,每个点有一种颜色.对于某一条线段,选择所有其上方或下方的点.求:在不包含所有颜色的点的前提下,选择的点数最多是多少.(本题中如果存在某颜色没有相应的点,那么选择任何线段都不算 ...
- wannafly 挑战赛10 小H和游戏
题解: 先利用dfs找出各个节点之间的关系.然后利用一个sum[i][j] 数组 sum[i][0] 表示i这个节点收到影响的次数 sum[i][1]表示i这个节点的儿子们收到影响的次数 sum[i ...
- wannafly 挑战赛10 小H和密码
题意:中文题就不解释了 题解: dp[i][j]表示前i 个轮盘 和一个字符串前j 个字符的匹配情况 ,具体的状态转移解释见代码 #include <cstdio> #include &l ...
- 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)
传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...
- H - 逆序数(树状数组)
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...
- 算法笔记求序列A每个元素左边比它小的数的个数(树状数组和离散化)
#include <iostream> #include <algorithm> #include <cstring> using namespace std ; ...
- 牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)
牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) 链接:https://ac.nowcoder.com/acm/problem/15706 现在需要您来帮忙维护这个名册, ...
- 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治
LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...
- hdu 4217 Data Structure? 树状数组求第K小
Data Structure? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
随机推荐
- C++CLR类库封装Native类库并用C#调用 - 草稿
1.创建Native类库 新建项目->其他语言->Visual C++->Win32控制台应用程序->DLL 添加头文件 添加源文件 选择生成路 ...
- LeetCoded第239题题解--滑动窗口最大值
滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 进 ...
- Wiring in Spring: @Autowired, @Resource and @Inject 区别
refer:https://www.baeldung.com/spring-annotations-resource-inject-autowire 主要是查找顺序不一致: @Resource Mat ...
- springcloud starter(一)
Spring Cloud - Getting Started Example, 转载自:https://www.logicbig.com/tutorials/spring-framework/spri ...
- 1TB是多大?
TB是计算机的存储单位,用来描述计算机的存储容量.另外还有GB.MB.KB.B.就像长度单位米.分米.厘米.毫米一样,它们之间有换算关系: 1KB = 1024B 1M = 1024KB 1GB = ...
- promise小案例
页面中有个板块,需要多张图片加载完之后才能进行显示 //页面中有个板块 需要多张图片加载完之后才能进行显示 const loadImg = (src) => { return new Promi ...
- PS-头发丝抠图
[PS版本]Photoshop CS5 [主题]头发丝抠图 [操作步骤] 第一步:打开待处理图片,复制图层: 第二步:快速选择工具选择主体(也可用魔术棒用具选择背景色,然后反向): 第三步:点击&qu ...
- 微信小程序 image 组件 src 请求不能设置 header 的问题
只能先 wx.downloadFile 得到 tempFilePath,然后设置 src = tempFilePath
- springboot通过AOP和自定义注解实现权限校验
自定义注解 PermissionCheck: package com.mgdd.sys.annotation; import java.lang.annotation.*; /** * @author ...
- MySQL——备份与恢复
MySQL数据库备份和恢复 --备份类型: 1.热备份(只有InnoDB支持)(不影响业务,最好的方式) 2.冷备份( 阻止用户访问) 3.温备份 --备份方式: 1.逻辑备份(文本表示:SQL语句) ...