标签:space top output string 关系 min opened als int
1 5 a 1 ab 2 abb 3 baba 5 abbab 8Sample Output
Case #1: 14
题解:
给定n个字符串,要求按顺序取一些字符串,满足后一个字符串是前一个字符串的子串,要求使得取出的权值和最大。
题目类似一般的DP问题,项最长上升子序列,只不过把上升的要求改成了是前一个的子串,权重也发生了改变 。
判断子串关系,我们用AC 自动机。
我们把AC自动机的fail指针拿出来建立一棵树,然后在求这棵树的dfs序,对于每个点,我所能得到的最大权值一定是该点到root的所有权值。然后我们对每个点的in[x],和out[x]之间的dfs序去更新。
每次取最大值即可
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; typedef long long LL; const int maxn=3e5+5; int cnt,root,n,kase,w[20000+5],pos[20000+5]; int INDEX,in[maxn],out[maxn]; char s[maxn]; int fail[maxn]; int S[maxn*4],tag[maxn*4],MAX,L,R; int st[maxn],tot; struct edge { int v,nxt; }v[maxn*2]; inline void addedge(int x,int y) { v[tot]=(edge){y,st[x]}; st[x]=tot++; } struct node { int nxt[26],cnt; }T[maxn]; inline int newnode() { cnt++; memset(T[cnt].nxt,0,sizeof(T[cnt].nxt)); T[cnt].cnt=0; fail[cnt]=0; return cnt; } inline void insert(char *s) { int now=root; int i=0; while(s[i]) { if(!T[now].nxt[s[i]-‘a‘])T[now].nxt[s[i]-‘a‘]=newnode(); now=T[now].nxt[s[i]-‘a‘]; i++; } T[now].cnt++; } queue<int>Q; inline void build() { Q.push(root); while(!Q.empty()) { int k=Q.front(); Q.pop(); if(k!=root)addedge(fail[k],k); for(int i=0;i<26;++i) { if(!T[k].nxt[i]){T[k].nxt[i]=T[fail[k]].nxt[i];continue;} if(k!=root) fail[T[k].nxt[i]]=T[fail[k]].nxt[i]; Q.push(T[k].nxt[i]); } } } inline void DFS(int u,int fa) { in[u]=++INDEX; for(int i=st[u];~i;i=v[i].nxt) if(v[i].v!=fa) DFS(v[i].v,u); out[u]=INDEX; } inline void update(int k) { S[k]=max(S[k<<1],S[k<<1|1]); } inline void down(int k) { if(!tag[k])return ; tag[k<<1]=max(tag[k<<1],tag[k]); tag[k<<1|1]=max(tag[k<<1|1],tag[k]); S[k<<1]=max(S[k<<1],tag[k]); S[k<<1|1]=max(S[k<<1|1],tag[k]); tag[k]=0; } inline int ask(int l,int r,int k) { if(L<=l&&r<=R)return S[k]; int mid=(l+r)>>1; down(k); int res=0; if(L<=mid)res=max(res,ask(l,mid,k<<1)); if(R>mid)res=max(res,ask(mid+1,r,k<<1|1)); return res; } inline void add(int l,int r,int k) { if(L<=l&&r<=R) { S[k]=max(S[k],MAX); tag[k]=max(tag[k],MAX); return ; } int mid=(l+r)>>1; down(k); if(L<=mid)add(l,mid,k<<1); if(R>mid)add(mid+1,r,k<<1|1); update(k); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); cnt=-1; root=newnode(); tot=0; memset(st,-1,sizeof(st)); pos[0]=0; for(int i=1;i<=n;++i) { scanf("%s%d",s+pos[i-1],w+i); pos[i]=pos[i-1]+strlen(s+pos[i-1]); insert(s+pos[i-1]); } build(); INDEX=0; DFS(root,-1); int ans=0; memset(S,0,sizeof(S)); memset(tag,0,sizeof(tag)); for(int i=1;i<=n;++i) { MAX=0; int p=root; for(int j=pos[i-1];j<pos[i];++j) { p=T[p].nxt[s[j]-‘a‘]; L=in[p];R=in[p]; int res=ask(1,INDEX,1); MAX=max(res,MAX); } MAX=MAX+w[i]; ans=max(ans,MAX); L=in[p];R=out[p]; add(1,INDEX,1); } printf("Case #%d: %d\n",++kase,ans); } return 0; }
HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)
标签:space top output string 关系 min opened als int
原文地址:https://www.cnblogs.com/songorz/p/11455717.html