程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> The 2011 ACM-ICPC ACRC]G.GRE Words

The 2011 ACM-ICPC ACRC]G.GRE Words

編輯:C++入門知識

題意:給定一張包含 N 個單詞的表,每個單詞有個價值 W。要求從中選出一個子序列使得其中的每個單詞是後一個單詞的子串,最大化子序列中 W 的和。 顯然有f[i] = max(f[j] + w[i]), j < i 且串j包含於串i。 將方程化為f[i] = max(f[j] + w[i]), j > i 且串i包含於串j。接著可以考慮用線段樹優化去max。 可以用AC自動機或後綴數組做,不過後綴數組由於構建復雜度和二分區間顯然要慢得多。 AC自動機code: [cpp]  #include <cstdio>   #include <cmath>   #include <cstdlib>   #include <cstring>   #include <ctime>   #include <cctype>   #include <map>   #include <set>   #include <string>   #include <vector>   #include <algorithm>   using namespace std;      #ifdef WIN32   #define fmt64 "%I64d"   #else   #define fmt64 "%lld"   #endif   #define PI M_PI   #define oo 0x13131313   #define PB push_back   #define PO pop_back   #define iter iterator   #define MP make_pair   #define fst first   #define snd second   #define cstr(a) (a).c_str()      #define FOR(i, j, k) for (i = (j); i <= (k); ++i)   #define ROF(i, j, k) for (i = (j); i >= (k); --i)   #define FER(i, j, k) for (i = j[k]; i; i = i->n)   #define FRE(i, a) for (i = (a).begin(); i != (a).end(); ++i)      typedef unsigned int uint;   typedef long long int64;   typedef unsigned long long uint64;   typedef long double real;      template<class T> inline bool minim(T &a, const T &b) {return b < a ? a = b, 1 : 0;}   template<class T> inline bool maxim(T &a, const T &b) {return b > a ? a = b, 1 : 0;}   template<class T> inline T sqr(const T &a) {return a * a;}      #define maxn 300005   #define maxk 20005      struct edge {int t; edge *n;}       es[maxn + maxk], *adj, *lst[maxn];      void link(int i, int j)   {       *(++adj) = (edge){j, lst[i]}, lst[i] = adj;   }      struct trie   {       edge *lst;       trie *c[26], *f, *fa;   }       root[maxn], *tt, *que[maxn], *tback[maxk];      void insert(char *st, int k)   {       trie *p = root;       for (; *st; p = p->c[*(st++) - 'a'])           if (!p->c[*st - 'a']) (p->c[*st - 'a'] = ++tt)->fa = p;       *(++adj) = (edge){k, p->lst}, p->lst = adj;       tback[k] = p;   }      void build()   {       int i, ll, rr;       (que[ll = rr = 1] = root)->f = root;       for (; ll <= rr; ++ll)           FOR(i, 0, 25) if (que[ll]->c[i]) {               trie *p = que[ll]->c[i], *q;               for (q = que[ll]->f; q != root && !q->c[i]; q = q->f);               p->f = q->c[i] && q->c[i] != p ? q->c[i] : root;               link(p->f - root, p - root);               que[++rr] = p;           }   }      int T, n, cnt, begin[maxk], end[maxk], mark[maxn];      void dfs()   {       int u, v; trie *p; edge *e;       for (mark[u = 0] = cnt = 0; ; )           if (!lst[u]) {               p = root + u;               for (e = p->lst; e; e = e->n) end[e->t] = cnt;               if (p->f == p) return; else u = p->f - root;           } else {               v = lst[u]->t, lst[u] = lst[u]->n;               u = v, p = root + u, mark[u] = ++cnt;               for (e = p->lst; e; e = e->n) begin[e->t] = cnt;           }   }      struct node   {       node *s, *t, *f;       int l, r, v;   }       ns[maxn*2], *nt, *nRT, *back[maxn];   int nL, nR, ans;      void build(node *&p, int l, int r)   {       p = ++nt, p->l = l, p->r = r, p->v = 0;       if (l == r) {back[l] = p; return;}       build(p->s, l, (l + r) >> 1);       build(p->t, ((l + r) >> 1) + 1, r);       p->s->f = p->t->f = p;   }      void insert(int pos, int k)   {       node *p = back[pos];       if (maxim(p->v, k))           for (p = p->f; p; p = p->f) {               k = max(p->s->v, p->t->v);               if (p->v == k) break; p->v = k;           }   }      void query(node *p)   {       if (nL <= p->l && p->r <= nR) {ans = p->v; return;}       if (nL <= p->s->r && p->s->v > ans) query(p->s);       if (p->t->l <= nR && p->t->v > ans) query(p->t);   }      int ask(int l, int r) {return nL = l, nR = r, ans = 0, query(nRT), ans;}      void prepare()   {       tt = root, memset(root, 0, sizeof root);       adj = es, memset(lst, 0, sizeof lst);       nt = ns;   }      char st[maxn]; int w[maxk];      int main()   {   #ifndef ONLINE_JUDGE       freopen("p3.in", "r", stdin);       freopen("p3.out", "w", stdout);   #endif       for (scanf("%d", &T); T--; ) {           int i, ans = 0;           prepare(), scanf("%d", &n);           FOR(i, 1, n) scanf("%s%d", st, w + i), insert(st, i);           build();           dfs();           build(nRT, 1, cnt);              ROF(i, n, 1) {               int k = ask(begin[i], end[i]) + w[i];               maxim(ans, k);               for (trie *p = tback[i]; p != root; p = p->fa)                   insert(mark[p - root], k);           }           printf("%d\n", ans);       }          return 0;   }   後綴數組code: [cpp]  #include <cstdio>   #include <cmath>   #include <cstdlib>   #include <cstring>   #include <ctime>   #include <cctype>   #include <map>   #include <set>   #include <string>   #include <vector>   #include <algorithm>   using namespace std;      #ifdef WIN32   #define fmt64 "%I64d"   #else   #define fmt64 "%lld"   #endif   #define PI M_PI   #define oo 0x13131313   #define PB push_back   #define PO pop_back   #define iter iterator   #define MP make_pair   #define fst first   #define snd second   #define cstr(a) (a).c_str()      #define FOR(i, j, k) for (i = (j); i <= (k); ++i)   #define ROF(i, j, k) for (i = (j); i >= (k); --i)   #define FER(i, j, k) for (i = j[k]; i; i = i->n)   #define FRE(i, a) for (i = (a).begin(); i != (a).end(); ++i)      typedef unsigned int uint;   typedef long long int64;   typedef unsigned long long uint64;   typedef long double real;      template<class T> inline bool minim(T &a, const T &b) {return b < a ? a = b, 1 : 0;}   template<class T> inline bool maxim(T &a, const T &b) {return b > a ? a = b, 1 : 0;}   template<class T> inline T sqr(const T &a) {return a * a;}      #define maxn 300005   #define maxk 20005   #define maxm 2005      typedef int array[maxn];   typedef int arr[maxk];      array sa, rank, sum, xx, yy, z, height, st;      void build(int &n, int &m)   {       int i, j, k; int *x = xx, *y = yy;       memset(sum, 0, sizeof(array));       FOR(i, 1, n) ++sum[x[i] = st[i]];       FOR(i, 2, m) sum[i] += sum[i - 1];       ROF(i, n, 1) sa[sum[x[i]]--] = i;       for (j = 1; m < n; j <<= 1, m = k) {           k = 0;           FOR(i, n - j + 1, n) y[++k] = i;           FOR(i, 1, n) if (sa[i] > j) y[++k] = sa[i] - j;           memset(sum, 0, sizeof(array));           FOR(i, 1, n) ++sum[z[i] = x[y[i]]];           FOR(i, 2, m) sum[i] += sum[i - 1];           ROF(i, n, 1) sa[sum[z[i]]--] = y[i];           swap(x, y), x[sa[1]] = k = 1;           FOR(i, 2, n) {               int p = sa[i], q = sa[i - 1];               x[p] = y[p] == y[q] && y[p + j] == y[q + j] ? k : ++k;           }       }       memcpy(rank, x, sizeof(array));          FOR(i, 1, n) {           j = sa[rank[i] - 1];           z[i] = z[i - 1] ? z[i - 1] - 1 : 0;           for (; st[i + z[i]] == st[j + z[i]]; ++z[i]);           height[rank[i]] = z[i];       }   }      int back[200], L, ans;   array belong;   arr w, len, begin, end;      void init(int &n, int &m)   {       int i, j, k;       memset(back, 0, sizeof back);          scanf("%d\n", &n), m = n;       int *ptr = st;       FOR(i, 1, n) {           begin[i] = k = j = ptr - st + 1;           for (*(++ptr) = getchar(); 'a' <= *ptr && *ptr <= 'z'; *(++ptr) = getchar()) {               if (!back[*ptr]) back[*ptr] = ++m;               *ptr = back[*ptr];               belong[k] = i, ++k;           }           *ptr = i, belong[end[i] = ptr - st] = 0;           len[i] = ptr - st - j;           scanf("%d\n", w + i);       }       L = ptr - st;   }      namespace rmq   {       array mini[19];          void prepare()       {           int i, j;           int *p = mini[0], *q;           FOR(i, 1, L) p[i] = height[i];           FOR(i, 1, 18) {               q = p, p = mini[i];               FOR(j, 1, L) p[j] = min(q[j], q[j + (1 << (i - 1))]);           }       }   }      namespace tree   {       struct node       {           node *s, *t, *f;           int l, r, v;       };          node ns[maxn*2], *nt = ns, *root, *back[maxn];       int L, R, ans;          void build(node *&p, int l, int r)       {           p = ++nt, p->l = l, p->r = r, p->v = 0;           if (l == r) {back[l] = p; return;}           build(p->s, l, (l + r) >> 1);           build(p->t, ((l + r) >> 1) + 1, r);           p->s->f = p->t->f = p;       }          void init(int r) {nt = ns; build(root, 1, r);}          void insert(int pos, int k)       {           node *p = back[pos]; p->v = k;           for (p = p->f; p; p = p->f) p->v = max(p->s->v, p->t->v);       }          void query(node *p)       {           if (L <= p->l && p->r <= R) {ans = p->v; return;}           if (L <= p->s->r && p->s->v > ans) query(p->s);           if (p->t->l <= R && p->t->v > ans) query(p->t);       }          int query(int l, int r) {return ans = 0, L = l, R = r, query(root), ans;}   }      void work(int n)   {       int i, j, k, l, x, y; ans = 0;       rmq::prepare(), tree::init(L);       ROF(i, n, 1) {           int pos = rank[begin[i]], ll, rr;           l = len[i], ll = rr = pos, ++rr;           ROF(j, 19, 0) if ((x = rr + (1 << j) - 1) < L)               if (rmq::mini[j][rr] >= l) rr = x;           ROF(j, 19, 0) if ((x = ll - (1 << j) + 1) > 0)               if (rmq::mini[j][x]  >= l) ll = x;              maxim(ans, k = tree::query(ll, rr) + w[i]);           x = begin[i], y = end[i];           for (j = x; j < y; ++j) tree::insert(rank[j], k);       }       printf("%d\n", ans);   }      int main()   {   #ifndef ONLINE_JUDGE       freopen("p3.in", "r", stdin);       freopen("p3.out", "w", stdout);   #endif  www.2cto.com     int T, n, m;       for (scanf("%d", &T); T--; ) {           init(n, m);           build(L, m);           work(n);       }          return 0;   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved