首先对所有单词建立AC自动机,$S$是$T$的子串等价于$T$的某个前缀通过$fail$链可以走到$S$的终止节点,即$S$的终止节点是$T$某个前缀在$fail$树上的祖先。

设$f[i]$表示考虑了前$i$个单词,且第$i$个单词必选时子序列价值的最大值,

则$f[i]=\max(单词i每个前缀的贡献)+w[i]$,计算出$f[i]$后再在单词$i$终止节点在$fail$树的子树里打上$f[i]$的标记,线段树维护即可。

时间复杂度$O(L\log L)$。

  1. #include<cstdio>
  2. #include<cstring>
  3. const int N=20010,M=300010;
  4. typedef long long ll;
  5. char s[M];
  6. int tot,son[M][26],fail[M],q[M],G[M],NXT[M],st[M],en[M],dfn;
  7. int Case,n,i,j,w[N],g[N],v[M],nxt[M],ed;
  8. ll tag[1050000],dp,ans;
  9. inline void ins(int p){
  10. for(int l=strlen(s),x=0,i=0,w;i<l;i++){
  11. if(!son[x][w=s[i]-'a'])son[x][w]=++tot;
  12. v[++ed]=x=son[x][w];nxt[ed]=g[p];g[p]=ed;
  13. }
  14. }
  15. void make(){
  16. int h=1,t=0,i,j,x;fail[0]=-1;
  17. for(i=0;i<26;i++)if(son[0][i])q[++t]=son[0][i];
  18. while(h<=t)for(x=q[h++],i=0;i<26;i++)
  19. if(son[x][i])fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i];
  20. else son[x][i]=son[fail[x]][i];
  21. }
  22. void dfs(int x){
  23. st[x]=++dfn;
  24. for(int i=G[x];i;i=NXT[i])dfs(i);
  25. en[x]=dfn;
  26. }
  27. void build(int x,int a,int b){
  28. tag[x]=0;
  29. if(a==b)return;
  30. int mid=(a+b)>>1;
  31. build(x<<1,a,mid),build(x<<1|1,mid+1,b);
  32. }
  33. inline void up(ll&a,ll b){if(a<b)a=b;}
  34. void change(int x,int a,int b,int c,int d){
  35. if(c<=a&&b<=d){up(tag[x],dp);return;}
  36. int mid=(a+b)>>1;
  37. if(c<=mid)change(x<<1,a,mid,c,d);
  38. if(d>mid)change(x<<1|1,mid+1,b,c,d);
  39. }
  40. void ask(int x,int a,int b,int c){
  41. up(dp,tag[x]);
  42. if(a==b)return;
  43. int mid=(a+b)>>1;
  44. if(c<=mid)ask(x<<1,a,mid,c);else ask(x<<1|1,mid+1,b,c);
  45. }
  46. int main(){
  47. scanf("%d",&Case);
  48. while(Case--){
  49. scanf("%d",&n);
  50. for(i=1;i<=n;i++)scanf("%s%d",s,&w[i]),ins(i);
  51. make();
  52. for(i=1;i<=tot;i++)NXT[i]=G[fail[i]],G[fail[i]]=i;
  53. dfs(0);
  54. build(1,1,dfn);
  55. for(ans=0,i=1;i<=n;i++){
  56. for(dp=0,j=g[i];j;j=nxt[j])ask(1,1,dfn,st[v[j]]);
  57. up(ans,dp+=w[i]);
  58. change(1,1,dfn,st[v[g[i]]],en[v[g[i]]]);
  59. }
  60. printf("%lld\n",ans);
  61. for(i=dfn=0;i<=tot;i++)for(fail[i]=G[i]=j=0;j<26;j++)son[i][j]=0;
  62. for(ed=tot=0,i=1;i<=n;i++)g[i]=0;
  63. }
  64. return 0;
  65. }

  

BZOJ2905 : 背单词的更多相关文章

  1. BZOJ2905: 背单词 AC自动机+fail树+线段树

    $zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...

  2. 【BZOJ2905】背单词 fail树+DFS序+线段树

    [BZOJ2905]背单词 Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行 ...

  3. 做中学(Learning by Doing)之背单词-扇贝网推荐

    做中学(Learning by Doing)之背单词-扇贝网推荐 看完杨贵福老师(博客,知乎专栏,豆瓣)的「继续背单词,8个月过去了」,我就有写这篇文章的冲动了,杨老师说: 有时候我会感觉非常后悔,如 ...

  4. “我爱背单词”beta版发布与使用说明

    我爱背单词BETA版本发布 第二轮迭代终于画上圆满句号,我们的“我爱背单词”beta版本已经发布. Beta版本说明 项目名称 我爱背单词 版本 Beta版 团队名称 北京航空航天大学计算机学院  拒 ...

  5. BZOJ4567[Scoi2016]背单词

    4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...

  6. 《我爱背单词》 Alpha版 发布说明

    ——发布地址(baidu网盘) http://pan.baidu.com/s/15omtB ——简介  <我爱背单词>是一款英语单词记忆和管理辅助软件,旨在帮助广大考生在短期内攻克GRE. ...

  7. [No000057]一个人默默背单词,小心被传染哦

    不日凛冬将至,全国各地,已有多名少侠因季节变化,出现了不同程度的四肢不勤.bd不分的症状.具体表现为—— 包大人在此高能预警:不想背单词,有可能你已经被传染了. 好好的,怎么突然不想背单词了 哈佛医学 ...

  8. [No000014]听说不背单词,考英语会是这种下场-我们为什么必须背单词?

    由于英语对于一个程序员来说,重要性你懂得.因此我会开始逐渐在博客上加入英语的一些东西. 听说不背单词,考英语会是这种下场 在中国, 「学英语」大抵遵循着这样一条 罗蒙诺索夫质量守恒定律 因为英语学着学 ...

  9. Supermemo背单词7周年纪念

    从2007年2月1日开始,用Supermemo背单词7周年了,在2013年11月21日将单词表Reset,重新开始Review以前背过的单词,并慢慢加入听写VOA时遇到的生词.

随机推荐

  1. [Effective JavaScript 笔记]第39条:不要重用父类的属性名

    假设想给上节讲的场景图库添加收集诊断信息的功能.这对于调试和性能分析很有用. 38条示例续 给每个Actor实例一个唯一的标识数. 添加标识数 function Actor(scene,x,y){ t ...

  2. iphone数据存储之-- Core Data的使用(一)

    http://www.cnblogs.com/xiaodao/archive/2012/10/08/2715477.html 一.概念 1.Core Data 是数据持久化存储的最佳方式 2.数据最终 ...

  3. select function in ruby

    http://ruby-doc.org/ http://ruby-doc.org/core-2.3.0/Array.html#method-i-select [1,2,3,4,5].select { ...

  4. C#开发实例 键盘篇

    键盘的操作控制: 键盘和鼠标一样是重要输入设备的一部分.开发过程中,会涉及到很多的键盘操作控制. 2.1获取键盘信息 ①获取组合键 Windows中有很多默认的组合键,如Ctrl+v,Ctrl+A.本 ...

  5. LNK2005 连接错误解决办法

    nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@ ...

  6. HDOJ 1878 欧拉回路 nyoj 42一笔画问题

    #include<cstdio> #include<cstring> ]; int find(int x) { if(visited[x]!=x) return find(vi ...

  7. C语言指针总结

    C语言中的精华是什么,答曰指针,这也是C语言中唯一的难点. C是对底层操作非常方便的语言,而底层操作中用到最多的就是指针,以后从事嵌入式开发的朋友们,指针将陪伴我们终身. 本文将从八个常见的方面来透视 ...

  8. 转MYSQL学习(二) 运算符

    MYSQL中的运算符很多,这一节主要讲MYSQL中有的,而SQLSERVER没有的运算符 安全等于运算符(<=>) 这个操作符和=操作符执行相同的比较操作,不过<=>可以用来判 ...

  9. JavaScript封装成类

    JavaScript在WEB编程中能起到很大的作用,将一些常用的功能写成JavaScript类库. 将下面代码保存为Common.js 类库功能: 1.Trim(str)--去除字符串两边的空格 2. ...

  10. 理解C#中的闭包

    闭包的概念 内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止.但该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值. 闭包的优点 使用闭包,我们可以轻松的访问外层函数定 ...