博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第九周 10.25-10.31
阅读量:5127 次
发布时间:2019-06-13

本文共 2262 字,大约阅读时间需要 7 分钟。

10.25

HDU 4117 

卡了很久的一个题目。比较综合。

看了很久题解还是各种写挫。

毕竟除了模拟题都没敲过那么长的。

 

题意:按顺序给N个单词,每个单词有权值,删去其中任意单词,使得前面的单词为后面单词的子串,求最大权值和。

做法:先建好AC自动机。

 

   最先想到的方法应该是这样的。

   定义dp[i]为以第i个串为最后一个串的答案。

   转移是dp[i]=max{W[i],dp[j]+W[i]}(j为i子串)

   那么只要再拿这N个单词在AC自动机上匹配一遍。

   每过一个节点相当于经过这个串的一个前缀。而这个节点的fail指向的是这个前缀的后缀。

   于是经过的每个节点时都通过fail一直走到root就遍历了这个串的所有子串。

   那么我们不妨定义f[u]为节点u所对应的单词的所有后缀的答案。

   那么可以用这种方法借助f[]来求出dp。

   

   然而这样是T的。

   于是考虑一种用线段树优化的方法。

   

   考虑到我们每次是顺着fail指针更新答案的。而且每次更新一个节点后只会影响fail指向它的节点。

   按照fail反向建树。这样每个父节点都是孩子节点的前缀。也就是每次更新一个节点后只影响它的子树。

   先在fail树上dfs一遍打好时间戳。

   线段树的每个节点维护时间戳所对应的fail树上节点的f[]值。

   于是按照段更新的区间最值线段树写就可以了。

   每次询问所有前缀的f[]。再更新末节点对应子树的f[]。

   所有取最大即为答案。

   

   最后防爆栈黑科技交C++。   

 

1 #pragma comment(linker, "/STACK:102400000,102400000")  2 #include 
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 const int maxnode=3e5+10,sigma_size=26; 9 const int maxn=2e4+10; 10 int n,p[maxn],W[maxn]; 11 char s[maxnode]; 12 13 //fail_tree 14 int cnt,headlist[maxnode]; 15 int timer,dfn[maxnode][2]; 16 struct e 17 { 18 int to,pre; 19 } edge[2*maxnode]; 20 21 void add(int from,int to) 22 { 23 cnt++; 24 edge[cnt].pre=headlist[from]; 25 edge[cnt].to=to; 26 headlist[from]=cnt; 27 } 28 29 void dfs(int pos,int fa) 30 { 31 dfn[pos][0]=++timer; 32 for(int i=headlist[pos];i;i=edge[i].pre) 33 { 34 int to=edge[i].to; 35 if(to==fa) continue; 36 dfs(to,pos); 37 } 38 dfn[pos][1]=++timer; 39 } 40 41 //seg_tree 42 struct seg_tree 43 { 44 int l,r,val; 45 }tree[maxnode<<3]; 46 47 void buildtree(int pos,int l,int r) 48 { 49 tree[pos].l=l; 50 tree[pos].r=r; 51 tree[pos].val=0; 52 if(l
=l&&tree[pos].r<=r) tree[pos].val=max(tree[pos].val,val); 68 else 69 { 70 pushdown(pos); 71 if((tree[pos].l+tree[pos].r)/2>=r) update(pos*2,l,r,val); 72 else if((tree[pos].l+tree[pos].r)/2
=l&&tree[pos].r<=r) return tree[pos].val; 84 int ret=0; 85 pushdown(pos); 86 if((tree[pos].l+tree[pos].r)/2>=r) ret=max(ret,query(pos*2,l,r)); 87 else if((tree[pos].l+tree[pos].r)/2
q;123 fail[0]=0;124 for(int i=0;i
Aguin

 

10.26-10.31

什么都没干。

转载于:https://www.cnblogs.com/Aguin/p/4908313.html

你可能感兴趣的文章
Linux内核态、用户态简介与IntelCPU特权级别--Ring0-3
查看>>
第23月第24天 git命令 .git-credentials git rm --cached git stash clear
查看>>
java SE :标准输入/输出
查看>>
[ JAVA编程 ] double类型计算精度丢失问题及解决方法
查看>>
好玩的-记最近玩的几个经典ipad ios游戏
查看>>
PyQt5--EventSender
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
tmux的简单快捷键
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
VC6.0调试技巧(一)(转)
查看>>
php match_model的简单使用
查看>>
SIP服务器性能测试工具SIPp使用指导(转)
查看>>
C# 类(10) 抽象类.
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
STM32单片机使用注意事项
查看>>
js window.open 参数设置
查看>>
032. asp.netWeb用户控件之一初识用户控件并为其自定义属性
查看>>
移动开发平台-应用之星app制作教程
查看>>
leetcode 459. 重复的子字符串(Repeated Substring Pattern)
查看>>
springboot No Identifier specified for entity的解决办法
查看>>