由易到难
e-Government CF 163E
http://blog.csdn.net/gyarenas/article/details/9315319
GRE Words hdu 4117
http://acm.hdu.edu.cn/showproblem.php?pid=4117
这题本来的做法是ac自动机优化dp,然而hdu加入了新的数据,估计构造了一些会导致fail链很长的数据,以前的做法会TLE,这就又需要我们维护fail树,用线段树维护fail树的dfs序列,支持单点修改区间求最值。需要注意的是当fail链比较短时(比如这题的原始数据),用线段树维护做法反而耗时更长。
一开始交上去各种优化各种MLE,后来发现原来是AC自动机初始化一下把整个数组置空了,特意找了篇oj判MLE的方法http://blog.csdn.net/a775700879/article/details/12521915,从这种情况来看,hdu用的方法应该和bnuoj一样
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <ctime> #include <bitset> #include <iomanip> #pragma comment(linker, "/STACK:102400000,102400000") using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; using std::multiset; using std::ios; using std::make_heap; using std::push_heap; using std::pop_heap; typedef long long LL; typedef unsigned long long ULL; typedef unsigned UN; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; typedef long double LF; const int MAXN(300010); const int MAXM(20010); const int MAXE(2100010); const int MAXK(6); const int HSIZE(1313131); const int SIGMA_SIZE(26); const int MAXH(18); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(1e13); const int INV(-10000); const int MOD(1000000007); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> inline bool checkmax(T &a, T b){if(b > a) { a = b; return true;} return false;} template<typename T> inline bool checkmin(T &a, T b){if(b < a) { a = b; return true;} return false;} template<typename T> inline T ABS(T a){return a < 0? -a: a;} template<typename T> inline bool EZ(T a){return ABS(a) < EPS;} struct SGT{ int val[MAXN << 2]; inline int ls(int rt){return rt << 1;} inline int rs(int rt){return (rt << 1)|1;} inline void push_up(int rt){val[rt] = max(val[ls(rt)], val[rs(rt)]);} void build(int l, int r, int rt){ val[rt] = -INFI; if(l == r) return; int m = (l+r) >> 1; build(l, m, ls(rt)); build(m+1, r, rs(rt)); } void update(int l, int r, int rt, int qi, int qv){ if(l == r){ checkmax(val[rt], qv); return; } // push_down(rt); int m = (l+r) >> 1; if(qi <= m) update(l, m, ls(rt), qi, qv); else update(m+1, r, rs(rt), qi, qv); push_up(rt); } int query(int l, int r, int rt, int ql, int qr){ if(ql <= l && qr >= r) return val[rt]; // push_down(rt); int m = (l+r) >> 1; int ret = -INFI; if(ql <= m) checkmax(ret, query(l, m, ls(rt), ql, qr)); if(qr > m) checkmax(ret, query(m+1, r, rs(rt), ql, qr)); return ret; } } sgt; int left[MAXN], right[MAXN], ind; struct TREE{ int *first, *v, *next; //内存优化,先借用线段树的内存 int rear; void init(int n){ first = sgt.val; v = sgt.val+MAXN; next = sgt.val+2*MAXN; memset(first, -1, sizeof(first[0])*n); rear = 0; } void insert(int tu, int tv){ v[rear] = tv; next[rear] = first[tu]; first[tu] = rear++; } void dfs(int u){ left[u] = ++ind; for(int i = first[u]; ~i; i = next[i]) dfs(v[i]); right[u] = ind; } } tree; int po[MAXM], sco[MAXM]; int front, back; struct AC{ int f[MAXN], ch[MAXN][SIGMA_SIZE], size; void init(){ memset(ch[0], 0, sizeof(ch[0])); // !!!memset(ch[0], 0, sizeof(ch)); size = 1; } void insert(char *sp, int i){ int rt = 0; for(; *sp; ++sp){ int id = *sp-'a'; if(!ch[rt][id]){ memset(ch[size], 0, sizeof(ch[size])); ch[rt][id] = size++; } rt = ch[rt][id]; } po[i] = rt; } void construct(){ front = back = 0; tree.init(size); for(int i = 0; i < SIGMA_SIZE; ++i) if(ch[0][i]){ f[ch[0][i]] = 0; tree.insert(0, ch[0][i]); left[back++] = ch[0][i]; } while(front < back){ int cur = left[front++]; for(int i = 0; i < SIGMA_SIZE; ++i){ int u = ch[cur][i]; if(u){ f[u] = ch[f[cur]][i]; tree.insert(f[u], u); left[back++] = u; } else ch[cur][i] = ch[f[cur]][i]; } } ind = 0; tree.dfs(0); } } ac; char str[MAXN+MAXM]; char *tst[MAXM]; int main(){ // freopen("d:\\in.txt", "r", stdin); // freopen("d:\\out.txt", "w", stdout); int TC, n_case(0); scanf("%d", &TC); while(TC--){ ac.init(); int n; scanf("%d", &n); tst[0] = str; for(int i = 0; i < n; ++i){ scanf("%s%d", tst[i], sco+i); tst[i+1] = tst[i]+strlen(tst[i])+1; ac.insert(tst[i], i); } ac.construct(); sgt.build(1, ind, 1); int ans = 0; for(int i = n-1; i >= 0; --i){ int temp = sgt.query(1, ind, 1, left[po[i]], right[po[i]]); checkmax(temp, 0); temp += sco[i]; int rt = 0; for(char *sp = tst[i]; *sp; ++sp){ int id = *sp-'a'; rt = ac.ch[rt][id]; sgt.update(1, ind, 1, left[rt], temp); } checkmax(ans, temp); } printf("Case #%d: %d\n", ++n_case, ans); } return 0; }
http://blog.csdn.net/gyarenas/article/details/9260235