题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序)

分析:

  其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多。

  对于这题来说,需要离线操作。dp转移也是很显然。

  但是由于数据比较大,所以普通的沿着fail指针往上走,逐步更新答案会TLE。

  考虑把fail指针反向,由于ac自动机的每个节点均有唯一的fail指针,若是沿着fail指针往上走,显然都会走到root,所以反向之后显然是一棵树,不妨称之为fail树。fail树有什么特点呢?可以画个图试试,如果儿子节点出现过,那么他的祖先显然也会出现!

  因此,正确的做法时:

  建立所有单词的AC自动机,对于每个节点的转移,都是从parent[]或者从fail[],fail[fail[]],...得到的。可以看出fail[]的关系形成一棵树,于是问题转化成,不断在节点处插入,询问点到根路径上的最大值,可以利用dfs序列转化用线段树维护。

  1. #include <queue>
  2. #include <vector>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <complex>
  6. #include <iostream>
  7. #include <algorithm>
  8.  
  9. using namespace std;
  10.  
  11. typedef long long ll;
  12. typedef unsigned long long ull;
  13.  
  14. #define debug puts("here")
  15. #define rep(i,n) for(int i=0;i<n;i++)
  16. #define rep1(i,n) for(int i=1;i<=n;i++)
  17. #define REP(i,a,b) for(int i=a;i<=b;i++)
  18. #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
  19. #define pb push_back
  20. #define RD(n) scanf("%d",&n)
  21. #define RD2(x,y) scanf("%d%d",&x,&y)
  22. #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
  23. #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
  24. #define All(vec) vec.begin(),vec.end()
  25. #define MP make_pair
  26. #define PII pair<int,int>
  27. #define PQ priority_queue
  28. #define cmax(x,y) x = max(x,y)
  29. #define cmin(x,y) x = min(x,y)
  30. #define Clear(x) memset(x,0,sizeof(x))
  31. #define lson rt<<1
  32. #define rson rt<<1|1
  33. #define SZ(x) x.size()
  34.  
  35. /******** program ********************/
  36.  
  37. const int MAXN = 3e5+5;
  38. const int kind = 26;
  39.  
  40. char s[MAXN];
  41. int beg[MAXN];
  42.  
  43. struct segTree {
  44. int l,r,mx;
  45. int cov;
  46. inline int mid() {
  47. return (l+r)>>1;
  48. }
  49. } tree[MAXN<<2];
  50.  
  51. void build(int l,int r,int rt) {
  52. tree[rt].l = l;
  53. tree[rt].r = r;
  54. tree[rt].cov = tree[rt].mx = 0;
  55. if(l==r)return;
  56. int mid = tree[rt].mid();
  57. build(l,mid,lson);
  58. build(mid+1,r,rson);
  59. }
  60.  
  61. void update(int rt){
  62. if(tree[rt].cov==0)return;
  63. cmax( tree[lson].cov,tree[rt].cov );
  64. cmax( tree[rson].cov,tree[rt].cov );
  65. cmax( tree[lson].mx,tree[rt].cov );
  66. cmax( tree[rson].mx,tree[rt].cov );
  67. tree[rt].cov = 0;
  68. }
  69.  
  70. void modify(int l,int r,int mx,int rt) {
  71. if(l<=tree[rt].l&&tree[rt].r<=r) {
  72. cmax(tree[rt].mx,mx);
  73. cmax(tree[rt].cov,mx);
  74. return;
  75. }
  76. update(rt);
  77. int mid = tree[rt].mid();
  78. if(r<=mid)modify(l,r,mx,lson);
  79. else if(l>mid)modify(l,r,mx,rson);
  80. else {
  81. modify(l,r,mx,lson);
  82. modify(l,r,mx,rson);
  83. }
  84. tree[rt].mx = max( tree[lson].mx,tree[rson].mx );
  85. }
  86.  
  87. int ask(int pos,int rt) {
  88. if(tree[rt].l==tree[rt].r)
  89. return tree[rt].mx;
  90. update(rt);
  91. int mid = tree[rt].mid();
  92. if(pos<=mid)return ask(pos,lson);
  93. else return ask(pos,rson);
  94. }
  95.  
  96. int ch[MAXN][kind],fail[MAXN];
  97. int val[MAXN];
  98. int st[MAXN],ed[MAXN];
  99. int tot,tim;
  100. vector<int> adj[MAXN];
  101.  
  102. inline void set(int x) {
  103. Clear(ch[x]);
  104. fail[x] = 0;
  105. adj[x].clear();
  106. }
  107. inline void init() {
  108. set(1);
  109. tot = 1;
  110. }
  111. inline int newNode() {
  112. set(++tot);
  113. return tot;
  114. }
  115. inline int ind(char c) {
  116. return c-'a';
  117. }
  118.  
  119. inline void ins(int x,int y,int val) {
  120. int r = 1;
  121. REP(i,x,y) {
  122. int c = ind(s[i]);
  123. if(ch[r][c]==0)
  124. ch[r][c] = newNode();
  125. r = ch[r][c];
  126. }
  127. }
  128.  
  129. inline void build() {
  130. queue<int> q;
  131. q.push(1);
  132. while(!q.empty()) {
  133. int r = q.front();
  134. q.pop();
  135. if(fail[r])
  136. adj[ fail[r] ].pb(r);
  137. rep(c,kind) {
  138. int x = ch[r][c];
  139. if(!x)continue;
  140. q.push(x);
  141.  
  142. int y = fail[r];
  143. while(y&&ch[y][c]==0)
  144. y = fail[y];
  145. fail[x] = y?ch[y][c]:1;
  146. }
  147. }
  148. }
  149.  
  150. void dfs(int x) {
  151. st[x] = ++ tim;
  152. foreach(i,adj[x]) {
  153. int y = adj[x][i];
  154. dfs(y);
  155. }
  156. ed[x] = tim;
  157. }
  158.  
  159. inline int run() {
  160. init();
  161.  
  162. int n;
  163. RD(n);
  164. rep1(i,n) {
  165. scanf("%s",s+beg[i-1]);
  166. RD(val[i]);
  167. beg[i] = beg[i-1]+strlen(s+beg[i-1]);
  168. ins(beg[i-1],beg[i]-1,val[i]);
  169. }
  170. build();
  171.  
  172. tim = 0;
  173. dfs(1);
  174. build(1,tim,1);
  175.  
  176. int ans = 0;
  177. rep1(i,n) {
  178. int r = 1;
  179. int now = 0;
  180. for(int j=beg[i-1]; j<beg[i]; j++) {
  181. int c = ind(s[j]);
  182. r = ch[r][c];
  183. cmax(now,ask( st[r],1 ));
  184. }
  185. now += val[i];
  186. modify(st[r],ed[r],now,1);
  187. cmax(ans,now);
  188. }
  189. return ans;
  190. }
  191.  
  192. int main() {
  193.  
  194. #ifndef ONLINE_JUDGE
  195. freopen("sum.in","r",stdin);
  196. //freopen("sum.out","w",stdout);
  197. #endif
  198.  
  199. int ssize = 128 << 20; // 256MB
  200. char *ppp = (char*)malloc(ssize) + ssize;
  201. __asm__("movl %0, %%esp\n" :: "r"(ppp) );
  202.  
  203. int ncase,Ncase = 0;
  204. RD(ncase);
  205. while(ncase--)
  206. printf("Case #%d: %d\n",++Ncase,run());
  207.  
  208. return 0;
  209. }

  

hdu 4117 GRE Words AC自动机DP的更多相关文章

  1. hdu 4117 -- GRE Words (AC自动机+线段树)

    题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...

  2. HDU 2296 Ring (AC自动机+DP)

    Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  3. HDU 2457 DNA repair (AC自动机+DP)

    题意:给N个串,一个大串,要求在最小的改变代价下,得到一个不含上述n个串的大串. 思路:dp,f[i][j]代表大串中第i位,AC自动机上第j位的最小代价. #include<algorithm ...

  4. HDU 2825 Wireless Password(AC自动机+DP)

    题目链接 做题, #include <cstdio> #include <string> #include <cstring> using namespace st ...

  5. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. HDU 3341 Lost's revenge AC自动机+dp

    Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...

  7. hdu 2296 aC自动机+dp(得到价值最大的字符串)

    Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  8. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  9. hdu 2457(ac自动机+dp)

    题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...

随机推荐

  1. android ViewConfiguration

    ViewConfiguration 1.有时候要获取一些android UI的中一些默认参数的来进行操作设置,就要用到ViewConfiguration 官方飞解释是:ViewConfiguratio ...

  2. 12.组合(Composition)

    组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合:它同样体现整体与部分间的关系,但此时整体与部分是不可分的,它们具有统一的生存期,整体的生命周期结 ...

  3. 学习C++的一些问题总结

    C++ 问题 (一) int main() { int i,j,m,n; i=8; j=10; m=++i+j++;  //++i是先递加再使用,j++是先使用再递加,故:9+10=19 n=++i+ ...

  4. plsql配置连接远程数据库

    一.首先安装PL/SQL Developer 下载地址:https://yunpan.cn/cM3njKpfK8MnT 访问密码 996a 二.再安装instantclient_11_2 下载地址:h ...

  5. 一条结合where、group、orderby的linq语法

    DataTable dt = (from x in dsResult.Tables[0].AsEnumerable() where DataTrans.CBoolean(x["IsCheck ...

  6. 测试HAPROXY的文件分流办法

    测试HAPROXY的文件分流办法 http://blog.chinaunix.net/uid-20553497-id-3054980.html http://blog.sina.com.cn/s/bl ...

  7. Java多线程技术学习笔记(一)

    目录: 概述 多线程的好处与弊端 JVM中的多线程解析 多线程的创建方式之一:继承Thread类 线程的状态 多线程创建的方式之二:实现Runnable接口 使用方式二创建多线程的好处 多线程示例 线 ...

  8. Task could not find "AxImp.exe" using the SdkToolsPath "C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\"

    本机v7.0A目录里没有AxImp.exe,无奈只能去官网下了个V7.1的. 安装完V7.1后,去“开始-所有程序-Microsoft Windows SDK v7.1”里找到Windows SDK ...

  9. Methods throughout the lifespan of a view controller

    Method                                DescriptionloadView                              Creates or re ...

  10. iOS7与iOS8的比較

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1c2h1d2VpMDIyNA==/font/5a6L5L2T/fontsize/400/fill/I0 ...