hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序)
分析:
其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多。
对于这题来说,需要离线操作。dp转移也是很显然。
但是由于数据比较大,所以普通的沿着fail指针往上走,逐步更新答案会TLE。
考虑把fail指针反向,由于ac自动机的每个节点均有唯一的fail指针,若是沿着fail指针往上走,显然都会走到root,所以反向之后显然是一棵树,不妨称之为fail树。fail树有什么特点呢?可以画个图试试,如果儿子节点出现过,那么他的祖先显然也会出现!
因此,正确的做法时:
建立所有单词的AC自动机,对于每个节点的转移,都是从parent[]或者从fail[],fail[fail[]],...得到的。可以看出fail[]的关系形成一棵树,于是问题转化成,不断在节点处插入,询问点到根路径上的最大值,可以利用dfs序列转化用线段树维护。
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <complex>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull; #define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
#define lson rt<<1
#define rson rt<<1|1
#define SZ(x) x.size() /******** program ********************/ const int MAXN = 3e5+5;
const int kind = 26; char s[MAXN];
int beg[MAXN]; struct segTree {
int l,r,mx;
int cov;
inline int mid() {
return (l+r)>>1;
}
} tree[MAXN<<2]; void build(int l,int r,int rt) {
tree[rt].l = l;
tree[rt].r = r;
tree[rt].cov = tree[rt].mx = 0;
if(l==r)return;
int mid = tree[rt].mid();
build(l,mid,lson);
build(mid+1,r,rson);
} void update(int rt){
if(tree[rt].cov==0)return;
cmax( tree[lson].cov,tree[rt].cov );
cmax( tree[rson].cov,tree[rt].cov );
cmax( tree[lson].mx,tree[rt].cov );
cmax( tree[rson].mx,tree[rt].cov );
tree[rt].cov = 0;
} void modify(int l,int r,int mx,int rt) {
if(l<=tree[rt].l&&tree[rt].r<=r) {
cmax(tree[rt].mx,mx);
cmax(tree[rt].cov,mx);
return;
}
update(rt);
int mid = tree[rt].mid();
if(r<=mid)modify(l,r,mx,lson);
else if(l>mid)modify(l,r,mx,rson);
else {
modify(l,r,mx,lson);
modify(l,r,mx,rson);
}
tree[rt].mx = max( tree[lson].mx,tree[rson].mx );
} int ask(int pos,int rt) {
if(tree[rt].l==tree[rt].r)
return tree[rt].mx;
update(rt);
int mid = tree[rt].mid();
if(pos<=mid)return ask(pos,lson);
else return ask(pos,rson);
} int ch[MAXN][kind],fail[MAXN];
int val[MAXN];
int st[MAXN],ed[MAXN];
int tot,tim;
vector<int> adj[MAXN]; inline void set(int x) {
Clear(ch[x]);
fail[x] = 0;
adj[x].clear();
}
inline void init() {
set(1);
tot = 1;
}
inline int newNode() {
set(++tot);
return tot;
}
inline int ind(char c) {
return c-'a';
} inline void ins(int x,int y,int val) {
int r = 1;
REP(i,x,y) {
int c = ind(s[i]);
if(ch[r][c]==0)
ch[r][c] = newNode();
r = ch[r][c];
}
} inline void build() {
queue<int> q;
q.push(1);
while(!q.empty()) {
int r = q.front();
q.pop();
if(fail[r])
adj[ fail[r] ].pb(r);
rep(c,kind) {
int x = ch[r][c];
if(!x)continue;
q.push(x); int y = fail[r];
while(y&&ch[y][c]==0)
y = fail[y];
fail[x] = y?ch[y][c]:1;
}
}
} void dfs(int x) {
st[x] = ++ tim;
foreach(i,adj[x]) {
int y = adj[x][i];
dfs(y);
}
ed[x] = tim;
} inline int run() {
init(); int n;
RD(n);
rep1(i,n) {
scanf("%s",s+beg[i-1]);
RD(val[i]);
beg[i] = beg[i-1]+strlen(s+beg[i-1]);
ins(beg[i-1],beg[i]-1,val[i]);
}
build(); tim = 0;
dfs(1);
build(1,tim,1); int ans = 0;
rep1(i,n) {
int r = 1;
int now = 0;
for(int j=beg[i-1]; j<beg[i]; j++) {
int c = ind(s[j]);
r = ch[r][c];
cmax(now,ask( st[r],1 ));
}
now += val[i];
modify(st[r],ed[r],now,1);
cmax(ans,now);
}
return ans;
} int main() { #ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif int ssize = 128 << 20; // 256MB
char *ppp = (char*)malloc(ssize) + ssize;
__asm__("movl %0, %%esp\n" :: "r"(ppp) ); int ncase,Ncase = 0;
RD(ncase);
while(ncase--)
printf("Case #%d: %d\n",++Ncase,run()); return 0;
}
hdu 4117 GRE Words AC自动机DP的更多相关文章
- hdu 4117 -- GRE Words (AC自动机+线段树)
题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...
- HDU 2296 Ring (AC自动机+DP)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2457 DNA repair (AC自动机+DP)
题意:给N个串,一个大串,要求在最小的改变代价下,得到一个不含上述n个串的大串. 思路:dp,f[i][j]代表大串中第i位,AC自动机上第j位的最小代价. #include<algorithm ...
- HDU 2825 Wireless Password(AC自动机+DP)
题目链接 做题, #include <cstdio> #include <string> #include <cstring> using namespace st ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 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 ...
- hdu 2296 aC自动机+dp(得到价值最大的字符串)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2457 DNA repair(AC自动机+DP)题解
题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...
- hdu 2457(ac自动机+dp)
题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...
随机推荐
- OC:方法
三种可见度 1.@public 被public 修饰的变量可以在外部(再声明一个新的类,也能访问) 和 该类的内部(在该类的.m文件内部)被访问,这样就可以在 main 函数中访问 @public 一 ...
- 3DSlicer源代码编译过程vs2008+windows xp [转]
一 下载QT源代码编译 1. 简述 在 Windows2000/xp/vista 下,安装 VS2008, QT 4.7.2 :并在 VS2008上建立 QT 的集成开发环境,利用 VS2008 ...
- jsp与El,jstl知识点总结归纳
jsp与El,jstl知识点总结归纳 jsp部分 一.jsp的三大指令 page ,include,taglib 1.jsp中的page指令 <% page %>-设置jsp 例如: &l ...
- Android vector标签 PathData 画图超详解
SVG是一种矢量图格式,是Scalable Vector Graphics三个单词的首字母缩写.在xml文件中的标签是<vector>,画出的图形可以像一般的图片资源使用,例子如下: &l ...
- CI reids 缓存
注意:在项目中的application/libraries 中自己定义的类最好不要以cache命名. 连接 Redis 服务器的配置信息必须保存到 application/config/redis.p ...
- C# 反射 通过类名创建类实例
“反射”其实就是利用程序集的元数据信息. 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间. 1.假设你要反射一个 DLL 中的类,并且没有引用它(即未知的类型): ...
- imindmap7_windows_7.0
思维导图工具: imindmap7_windows_7.0 iMindMap7.0 和谐包V1.0 22:27:23
- 抛砖引玉:关于Android的ListView中CheckBox错乱
首先:参考了这篇翻译的文章:http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html 文章中关于说的Android中的Recyc ...
- 微信公共服务平台开发(.Net 的实现)6-------自定义菜单
用户自定义菜单制作时,需要用到access_token,我们直接使用前面讲解的IsExistAccess_Token()函数.我理解的微信公共平台里面菜单分为button和sub_button,即菜单 ...
- getFields()和getDeclaredFields()
getFields()获得某个类的所有的公共(public)的字段,包括父类. getDeclaredFields()获得某个类的所有申明的字段,即包括public.private和proteced, ...