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 ...
随机推荐
- android ViewConfiguration
ViewConfiguration 1.有时候要获取一些android UI的中一些默认参数的来进行操作设置,就要用到ViewConfiguration 官方飞解释是:ViewConfiguratio ...
- 12.组合(Composition)
组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合:它同样体现整体与部分间的关系,但此时整体与部分是不可分的,它们具有统一的生存期,整体的生命周期结 ...
- 学习C++的一些问题总结
C++ 问题 (一) int main() { int i,j,m,n; i=8; j=10; m=++i+j++; //++i是先递加再使用,j++是先使用再递加,故:9+10=19 n=++i+ ...
- plsql配置连接远程数据库
一.首先安装PL/SQL Developer 下载地址:https://yunpan.cn/cM3njKpfK8MnT 访问密码 996a 二.再安装instantclient_11_2 下载地址:h ...
- 一条结合where、group、orderby的linq语法
DataTable dt = (from x in dsResult.Tables[0].AsEnumerable() where DataTrans.CBoolean(x["IsCheck ...
- 测试HAPROXY的文件分流办法
测试HAPROXY的文件分流办法 http://blog.chinaunix.net/uid-20553497-id-3054980.html http://blog.sina.com.cn/s/bl ...
- Java多线程技术学习笔记(一)
目录: 概述 多线程的好处与弊端 JVM中的多线程解析 多线程的创建方式之一:继承Thread类 线程的状态 多线程创建的方式之二:实现Runnable接口 使用方式二创建多线程的好处 多线程示例 线 ...
- 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 ...
- Methods throughout the lifespan of a view controller
Method DescriptionloadView Creates or re ...
- iOS7与iOS8的比較
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1c2h1d2VpMDIyNA==/font/5a6L5L2T/fontsize/400/fill/I0 ...