bzoj 2905 背单词
生活随笔
收集整理的這篇文章主要介紹了
bzoj 2905 背单词
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
給定一張包含N個單詞的表,每個單詞有個價值W。要求從中選出一個子序列使得其
中的每個單詞是后一個單詞的子串,最大化子序列中W的和。?
?
Input
第一行一個整數TEST,表示數據組數。?
接下來TEST組數據,每組數據第一行為一個整數N。?
接下來N行,每行為一個字符串和一個整數W。?
Output
TEST行,每行一個整數,表示W的和的最大值。?
?
?
數據規模?
設字符串的總長度為Len?
30.的數據滿足,TEST≤5,N≤500,Len≤10^4?
100.的數據滿足,TEST≤10,N≤20000,Len≤3*10^5
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 300020 7 8 typedef long long ll; 9 struct node{ 10 int ls,rs; 11 ll mx,tag; 12 }sgt[maxn * 2]; 13 struct node2{ 14 int next,to; 15 }e[maxn * 2]; 16 int head[maxn],cnt; 17 char ch[maxn]; 18 int T,n; 19 int nxt[maxn][26],tot,dfstime,fa[maxn]; 20 int fail[maxn],rt,cur,l[maxn],r[maxn],rec[maxn],w[maxn]; 21 int q[maxn],tt,hh; 22 ll f[maxn],ans; 23 24 inline void clear(){ 25 for (int i = 1 ; i <= n ; i++) f[i] = 0; 26 for (int i = 0 ; i <= tot ; i++) fail[i] = l[i] = r[i] = head[i] = fa[i] = rec[i] = 0; 27 for (int i = 1 ; i <= tot ; i++) e[i].next = e[i].to = 0; 28 for (int i = 0 ; i <= tot ; i++) memset(nxt[i],0,sizeof(nxt[i])); 29 for (int i = 1 ; i <= cnt ; i++) sgt[i].tag = sgt[i].mx = 0 , sgt[i].ls = sgt[i].rs = 0; 30 tot = cnt = dfstime = 0; 31 ans = 0; 32 } 33 inline void adde(int x,int y){ 34 e[++cnt].to = y; 35 e[cnt].next = head[x]; 36 head[x] = cnt; 37 } 38 inline void insert(int x){ 39 if ( !nxt[cur][x] ) nxt[cur][x] = ++tot , fa[tot] = cur; 40 cur = nxt[cur][x]; 41 } 42 void dfs(int x){ 43 if ( x ) l[x] = ++dfstime; 44 for (int i = head[x] ; i ; i = e[i].next) dfs(e[i].to); 45 r[x] = dfstime; 46 } 47 void build(int &x,int l,int r){ 48 x = ++cnt; 49 if ( l == r ) return; 50 int mid = (l + r) >> 1; 51 build(sgt[x].ls,l,mid); 52 build(sgt[x].rs,mid + 1,r); 53 } 54 void build_AC(){ 55 tt = hh = 0; 56 for (int i = 0 ; i < 26 ; i++) if ( nxt[0][i] ) q[tt++] = nxt[0][i]; 57 while ( hh < tt ){ 58 int x = q[hh++]; 59 for (int i = 0 ; i < 26 ; i++){ 60 if ( nxt[x][i] ){ 61 int p = fail[x]; 62 while ( !nxt[p][i] && p ) p = fail[p]; 63 fail[nxt[x][i]] = nxt[p][i]; //不是p 64 q[tt++] = nxt[x][i]; 65 } 66 } 67 } 68 for (int i = 1 ; i <= tot ; i++) adde(fail[i],i); 69 dfs(0); 70 cnt = 0; 71 build(rt,1,tot); 72 } 73 inline void update(int x){ 74 sgt[x].mx = max(sgt[sgt[x].ls].mx,sgt[sgt[x].rs].mx); 75 } 76 inline void add(int x,ll d){ 77 sgt[x].tag = max(sgt[x].tag,d); 78 sgt[x].mx = max(sgt[x].mx,d); 79 } 80 inline void pushdown(int x){ 81 if ( sgt[x].tag != 0 ){ 82 add(sgt[x].ls,sgt[x].tag); 83 add(sgt[x].rs,sgt[x].tag); 84 sgt[x].tag = 0; 85 } 86 } 87 void modify(int x,int l,int r,int ls,int rs,ll d){ 88 if ( ls <= l && rs >= r ){ 89 add(x,d); 90 return; 91 } 92 pushdown(x); 93 int mid = (l + r) >> 1; 94 if ( ls <= mid ) modify(sgt[x].ls,l,mid,ls,rs,d); 95 if ( rs > mid ) modify(sgt[x].rs,mid + 1,r,ls,rs,d); 96 update(x); 97 } 98 ll query(int x,int l,int r,int id){ 99 if ( l == r ) return sgt[x].mx; 100 pushdown(x); 101 int mid = (l + r) >> 1; 102 if ( id <= mid ) return query(sgt[x].ls,l,mid,id); 103 return query(sgt[x].rs,mid + 1,r,id); 104 } 105 void Dodp(){ 106 for (int i = 1 ; i <= n ; i++){ 107 int p = rec[i]; 108 while ( p ){ 109 f[i] = max(f[i],query(rt,1,tot,l[p])); 110 p = fa[p]; 111 } 112 f[i] += w[i]; 113 f[i] = max(0ll,f[i]); 114 modify(rt,1,tot,l[rec[i]],r[rec[i]],f[i]); 115 } 116 for (int i = 1 ; i <= n ; i++) ans = max(ans,f[i]); 117 } 118 int main(){ 119 freopen("input.txt","r",stdin); 120 scanf("%d",&T); 121 while ( T-- ){ 122 clear(); 123 scanf("%d",&n); 124 for (int i = 1 ; i <= n ; i++){ 125 scanf("%s",ch) , scanf("%d",&w[i]); 126 int l = strlen(ch); 127 cur = 0; 128 for (int j = 0 ; j < l ; j++){ 129 insert(ch[j] - 'a'); 130 } 131 rec[i] = cur; 132 } 133 build_AC(); 134 Dodp(); 135 printf("%lld\n",ans); 136 } 137 return 0; 138 }
?
轉載于:https://www.cnblogs.com/zqq123/p/5505824.html
總結
以上是生活随笔為你收集整理的bzoj 2905 背单词的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html快闪软件制作,阿勇pr:如何使用
- 下一篇: vue 基于网易云API的短信验证码登录