AC自动机fail树上dfs序建线段树+动态memset清空
题意:http://acm.hdu.edu.cn/showproblem.php?pid=4117
思路:https://blog.csdn.net/u013306830/article/details/77586562
主要就是卡你内存,AC自动机的字典树得要用了再清空。
代码有点长吧。。。
#include <cstdio>//sprintf islower isupper
#include <iostream>//pair
#include <string.h>//strstr substr strcat
#include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
#define mem(a,b) memset(a,b,sizeof(a))
#define pr printf
#define sc scanf
#define ls rt<<1
#define rs rt<<1|1
const int N=3e5+; char s[N];
int pos[],val[];
//-------------------------------
class mymap
{
public:
int tot;
int head[N];
int SZ[N];
int dfn[N],cnt;
struct
{
int to,next;
}edge[N];
void Init(int n)
{
tot=;
cnt=-;
for(int i=;i<=n;++i)
head[i]=SZ[i]=;
}
void add(int from,int to)
{
++tot;
edge[tot].to=to;
edge[tot].next=head[from];
head[from]=tot;
}
int dfs(int u)
{
++cnt;
dfn[u]=cnt;
SZ[dfn[u]]=;
for(int i=head[u];i;i=edge[i].next)
{
// cout<<edge[i].first<<endl;
SZ[dfn[u]]+=dfs(edge[i].to);
}
return SZ[dfn[u]];
}
}TREE; class seg_tree
{
public:
int max_[N<<],add[N<<]; void up(int rt)
{
max_[rt]=max(max_[ls],max_[rs]);
}
void dn(int rt)
{
if(add[rt])
{
add[ls]=max(add[ls],add[rt]);
add[rs]=max(add[rs],add[rt]);
max_[ls]=max(max_[ls],add[rt]);
max_[rs]=max(max_[rs],add[rt]);
add[rt]=;
}
}
void Build(int l,int r,int rt)
{
max_[rt]=;
add[rt]=;
if(l==r)
{
return;
}
int mid=(l+r)>>; Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
}
int Q_dot(int pos,int l,int r,int rt)
{
if(l==r)
{
return max_[rt];
} int mid=(l+r)>>;
dn(rt);
if(pos<=mid)
return Q_dot(pos,l,mid,rt<<);
else
return Q_dot(pos,mid+,r,rt<<|);
}
void update_qu(int L,int R,int V,int l,int r,int rt)
{
if(L>R)return;
if(L<=l&&r<=R)
{
max_[rt]=max(max_[rt],V);
add[rt]=max(add[rt],V);
return;
} int mid=(l+r)>>;
dn(rt);
if(L<=mid)
update_qu(L,R,V,l,mid,rt<<);
if(R>mid)
update_qu(L,R,V,mid+,r,rt<<|);
up(rt);
}
}SEG; class ac_automaton
{
public:
int tot;
int trie[N][];
int fail[N];
//other
//--------------
void Insert(int l,int r)
{
int rt=;
for(int i=l;i<=r;++i)
{
int id=s[i]-'a'+;
if(!trie[rt][id])
{
mem(trie[++tot],);
trie[rt][id]=tot;
}
rt=trie[rt][id];
}
}
queue<int>q;
void Getfail()
{
for(int i=;i<=;++i)
{
int id=trie[][i];
if(id)
{
fail[id]=;
q.push(id);
}
}
while(!q.empty())
{
int rt=q.front();q.pop();
for(int i=;i<=;++i)
{
int id=trie[rt][i];
if(id)
{
fail[id]=trie[fail[rt]][i];
q.push(id);
}
else
trie[rt][i]=trie[fail[rt]][i];
}
}
}
int Find(int l,int r,int id,int n)
{
int rt=;
int pos=;
int temp_max=;
for(int i=l;i<=r;++i)
{
rt=trie[rt][s[i]-'a'+];
pos=TREE.dfn[rt];
int temp_val=SEG.Q_dot(pos,,n,)+val[id];
temp_max=max(temp_max,temp_val);
}
SEG.update_qu(pos,pos+TREE.SZ[pos]-,temp_max,,n,);
// for(int j=1;j<=n;++j)pr("%d ",SEG.Q_dot(j,1,n,1));
// cout<<endl<<"----------------------------------"<<endl;
return temp_max;
}
}AC; void solve()
{
AC.tot=;
mem(AC.trie[],);
int n,tot;
sc("%d",&n);
pos[]=;
for(int i=;i<=n;++i)
{
sc("%s %d",s+pos[i],&val[i]);
int l=strlen(s+pos[i]);
AC.Insert(pos[i],pos[i]+l-);
pos[i+]=pos[i]+l;
}
tot=AC.tot;
// pr("%s\n",s+1);
AC.Getfail();
TREE.Init(tot);
SEG.Build(,tot,);
for(int i=;i<=AC.tot;++i)
TREE.add(AC.fail[i],i);
TREE.SZ[]=TREE.dfs();
int ans=;
for(int i=;i<=n;++i)
ans=max(ans,AC.Find(pos[i],pos[i+]-,i,tot));
pr("%d\n",ans);
} int main()
{
int T,cnt=;
sc("%d",&T);
while(T--)
{
pr("Case #%d: ",++cnt);
solve();
}
return ;
} /**************************************************************************************/
AC自动机fail树上dfs序建线段树+动态memset清空的更多相关文章
- CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)
题意:有N个串,给出的形式是拼接给出,对于第i行: (1,c)表示字符串i是单个字母c: (2,p,c)表示字符串i=在字符串p后面接上一个字母c. 然后给出M个提问,形式是(i,string).问 ...
- bzoj3306: 树(dfs序+倍增+线段树)
比较傻逼的一道题... 显然求子树最小值就是求出dfs序用线段树维护嘛 换根的时候树的形态不会改变,所以我们可以根据相对于根的位置分类讨论. 如果询问的x是根就直接输出整棵树的最小值. 如果询问的x是 ...
- URAL 1890 . Money out of Thin Air (dfs序hash + 线段树)
题目链接: URAL 1890 . Money out of Thin Air 题目描述: 给出一个公司里面上司和下级的附属关系,还有每一个人的工资,然后有两种询问: 1:employee x y z ...
- ac自动机fail树上按询问建立上跳指针——cf963D
解法看着吓人,其实就是为了优化ac自动机上暴力跳fail指针.. 另外这题对于复杂度的分析很有学习价值 /* 给定一个母串s,再给定n个询问(k,m) 对于每个询问,求出长度最小的t,使t是s的子串, ...
- 7月13日考试 题解(DFS序+期望+线段树优化建图)
T1 sign 题目大意:给出一棵 N 个节点的树,求所有起点为叶节点的有向路径,其 上每一条边权值和的和.N<=10000 水题.考试的时候毒瘤出题人(学长orz)把读入顺序改了一下,于是很多 ...
- bzoj2819 DFS序 + LCA + 线段树
https://www.lydsy.com/JudgeOnline/problem.php?id=2819 题意:树上单点修改及区间异或和查询. 思维难度不高,但是题比较硬核. 整体思路是维护每一个结 ...
- hdu 3974 Assign the task(dfs序上线段树)
Problem Description There is a company that has N employees(numbered from 1 to N),every employee in ...
- Codeforces 877E - Danil and a Part-time Job(dfs序+线段树)
877E - Danil and a Part-time Job 思路:dfs序+线段树 dfs序:http://blog.csdn.net/qq_24489717/article/details/5 ...
- 用dfs序处理线段树的好题吗?
https://www.cnblogs.com/mountaink/p/9878918.html 分析:每次的选取必须选最优的一条链,那我们考虑一下选择这条链后,把这条路上的点的权值更新掉,再采取选最 ...
随机推荐
- MySQL数据分析-(9)库操作补充:用户管理和权限管理
大家好,我是jacky,很高兴继续跟大家学习MySQL数据分析实战,本节课的主题是用户管理和权限管理: 在分享之前,jacky在不厌其烦的强调一下:学习任何一门学科和技能,最重要的是捋清逻辑,我们要知 ...
- c 判断是否为 字母或数字(iswalnum example)
#include <stdio.h> #include <wctype.h> int main () { int i; wchar_t str[] = L"c3p.o ...
- gitlab配置邮箱postfix(新用户激活邮件)
亲测可用 https://www.cnblogs.com/yoyoketang/p/10287345.html
- Raspberry Pi 摄像头模块入门
目录 一.摄像头模块安装 二.使用命令控制摄像头 三.使用Python程序控制摄像头 四.基于vlc的Raspberry Pi摄像头实时监控 参考资料 Raspberry Pi提供了摄像头模块的接口, ...
- jdbc相比于hibernate的弊端
1.编程人员必须既懂Java语言,又懂SQL语言,才能编写数据库访问代码.(感觉用不用hibernate,SQL都要会呀) 2.程序代码中嵌入大量字符串形式的SQL语句,降低了程序代码的可读性. 3. ...
- 2018-2019-2 20175227张雪莹《Java程序设计》实验五 《网络编程与安全》
2018-2019-2 20175227张雪莹<Java程序设计> 实验五 <网络编程与安全> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号:20 ...
- nltk data 离线安装
运行程序时发现如下错误: 在命令行下载速度太慢,因此需要离线安装: 按照:http://www.nltk.org/data.html 中manual installation的方法, 将包下载好后解压 ...
- HTTP之持久连接
HTTP/1.1 允许 HTTP 设备在事务处理结束之后将 TCP 连接保持在打开状态,以便为未来的 HTTP 请求重用现存的连接.在事务处理结束后仍然保持在打开状态的 TCP 连接被称为持久连接.非 ...
- P1944 最长括号匹配_NOI导刊2009提高(1)
P1944 最长括号匹配_NOI导刊2009提高 题解 宁愿相信世上有鬼,也不能随便相信某谷题目标签 我想了半天然后看了眼题解,发现用栈来模拟就好了 栈来模拟,还要用到一个bool数组,标记是否已经匹 ...
- linux下什么工具可以用来纠正文件中的拼写和排版错误?
答: ispell,官网在此