HDU 4117 GRE Words
這道題不難想到這樣的dp。
dp[字符串si] = 以si為結(jié)尾的最大總權(quán)值。
dp[si] = max(dp[sj]) ,1.j < i,2.sj是si的子串。
對(duì)于第二個(gè)條件,是一個(gè)多模版串匹配的問(wèn)題,可以用AC自動(dòng)機(jī)。
預(yù)先O(m)把AC自動(dòng)機(jī)建好,然后動(dòng)態(tài)更新AC自動(dòng)機(jī)上的dp值,
匹配的時(shí)候,指向字符的指針移動(dòng)總共是O(m),
而每個(gè)單詞,fail指針走尋找后綴卻是O(m),即使改成后綴鏈接也是O(n)。too slow!
找到一個(gè)單詞后,需要避免找后綴,動(dòng)態(tài)維護(hù)這個(gè)單詞的dp值。
一開(kāi)始所有單詞的dp都是0。
更新的時(shí)候,dp[si]需要更新所有dp[sj],其中si是sj的后綴。
如果父節(jié)點(diǎn)是子節(jié)點(diǎn)的后綴,把所有的單詞(包括空后綴)連接起來(lái)將會(huì)得到以空字符串為根的后綴鏈接樹(shù)。
這樣就變成一個(gè)更新子樹(shù)的問(wèn)題,dfs把樹(shù)形轉(zhuǎn)成線性以后可以用線段樹(shù)來(lái)維護(hù)。
詢問(wèn)單點(diǎn)最大值,區(qū)間更新O(logn)。
復(fù)雜度O(mlogn)
潛在的坑點(diǎn):
1.Trie個(gè)結(jié)點(diǎn)可能對(duì)應(yīng)多個(gè)單詞,如果只更新了其中一個(gè)單詞的線性區(qū)間RE...(map,前向鏈表,vector都可以搞
?
/********************************************************* * ------------------ * * author AbyssFish * **********************************************************/ #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std;const int LEN = 3e5+5; const int MAXN = 2e4+5;int W[MAXN], S[MAXN]; int N; char s[LEN];int hd[LEN]; int nx[MAXN], to[MAXN], ec;void add_e(int u,int v) {to[ec] = v;nx[ec] = hd[u];hd[u] = ec++; } #define eachedge int i = hd[u]; ~i; i = nx[i] inline void init_g(int n){ memset(hd,-1,n<<2); ec = 0; } int L[MAXN], R[MAXN], dfs_clk; //string's linear suffix link tree id const int ST_SIZE = 1<<16; int dp[ST_SIZE];#define para int o = 1,int l = 0,int r = dfs_clk #define lo (o<<1) #define ro (o<<1|1) #define Tvar int md = (l+r)>>1; #define lsn lo,l,md #define rsn ro,md,r #define insd ql<=l&&r<=qrvoid build(para) {dp[o] = 0;if(r-l>1){Tvarbuild(lsn);build(rsn);} }void update(int ql,int qr,int v,para) {if(insd){dp[o] = max(dp[o],v);}else {Tvarif(ql < md) update(ql,qr,v,lsn);if(qr > md) update(ql,qr,v,rsn);} }int query(int p,para) {int re = 0;while(r-l>1){Tvarif(p<md){o = lo; r = md;}else {o = ro; l = md;}re = max(re,dp[o]);}return re; }const int sigma_size = 26, MAXND = LEN; struct AhoCorasick_automata {#define idx(x) (x-'a')int ch[MAXND][sigma_size];int f[MAXND];int last[MAXND];int cnt;int val[MAXND];int nx_val[MAXN];void add_v(int o,int x){nx_val[x] = val[o];val[o] = x;}int newNode(){int i = ++cnt;memset(ch[i],0,sizeof(ch[i]));val[i] = 0;return i;}void init(){cnt = -1; newNode();}int add(char *s,int id){int u = 0, i, c;for(i = 0; s[i]; i++){c = idx(s[i]);if(!ch[u][c]){ch[u][c] = newNode();}u = ch[u][c];}add_v(u,id);return i;}queue<int> q;void getFail(){int u, c, v, r;//f[0] = 0; last[0] = 0;for(c = 0; c < sigma_size; c++){u = ch[0][c];if(u){q.push(u);f[u] = 0;last[u] = 0;}}while(!q.empty()){r = q.front(); q.pop();for(c = 0; c < sigma_size; c++){u = ch[r][c];if(u){q.push(u);v = f[u] = ch[f[r]][c];last[u] = val[v] ? v : last[v];}else ch[r][c] = ch[f[r]][c];}}}void dfs(int u){int le = dfs_clk++;for(eachedge){dfs(to[i]);}int ri = dfs_clk;for(int id = val[u]; id; id = nx_val[id]){L[id] = le; R[id] = ri;}}void buildTree(){init_g(cnt+1);for(int u = 1; u <= cnt; u++)if(val[u]){add_e(last[u],u);}dfs_clk = 0;dfs(0);}void work(){int i,j,c,u,id;int ans = 0, mx;build();for(i = 1; i <= N; i++){u = 0; mx = 0;for(j = S[i-1]; j < S[i]; j++){c = idx(s[j]);u = ch[u][c];if(val[u]){id = val[u];mx = max(mx, query(L[id]));}else if(last[u]){id = val[last[u]];mx = max(mx, query(L[id]));}}if(W[i] > 0){ans = max(ans, mx += W[i]);update(L[i],R[i],mx);}}printf("%d\n",ans);}}ac;void solve() {scanf("%d",&N);ac.init();for(int i = 1; i <= N; i++){scanf("%s%d",s+S[i-1],W+i);S[i] = ac.add(s+S[i-1],i)+S[i-1];}ac.getFail();ac.buildTree();ac.work(); }//#define LOCAL int main() { #ifdef LOCALfreopen("data.txt","r",stdin); #endifint T, kas = 0; scanf("%d",&T);while(++kas <= T){printf("Case #%d: ",kas);solve();}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/jerryRey/p/5051900.html
總結(jié)
以上是生活随笔為你收集整理的HDU 4117 GRE Words的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: unity 中文 离线文档下载安装
- 下一篇: 【人脸姿态】2D人脸姿态估计的两种方式: