Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
DP + Trie, 做了两天... 上shi一样的代码...调试了大半天, 打log打到要吐... 本以为用trie效率能高一点,没想到还是一样的shi... 2124K 563MS... 哪位大牛帮忙指点指点怎样能优化一下? #include <iostream> #include <stack> using namespace std; class Trie{ public: bool end; Trie *parent; Trie *child[26]; Trie(); Trie(Trie *p); ~Trie(); }; Trie::Trie(){ end = false; parent = NULL; for(int i = 0; i < 26; ++i){ if(child[i]){ child[i] = NULL; } } } Trie::Trie(Trie *p){ end = false; parent = p; for(int i = 0; i < 26; ++i){ if(child[i]){ child[i] = NULL; } } } Trie::~Trie(){ for(int i = 0; i < 26; ++i){ if(child[i]){ delete child[i]; child[i] = NULL; } } } void AddWord(string s, Trie &t){ int len = s.size(); Trie *p = &t; for(int i = 0; i < len; ++i){ int index = s[i] - 97; if(p->child[index] == NULL){ p->child[index] = new Trie(p); } p = p->child[index]; } p->end = true; } //找当前节点的下一个兄弟节点 int NextChild(Trie *prev, Trie **Child){ int pos = -1; if(prev!=NULL){ for(int i = 0; i < 26; ++i){ if(Child[i] == prev) pos = i; } } for(int i = pos + 1; i < 26; ++i){ if(Child[i] != NULL) return i; } return -1; } int main(){ int w_count, msg_len; cin>>w_count>>msg_len; string s[600]; string msg; cin>>msg; for(int i = 0; i < w_count; ++i){ cin>>s[i]; } Trie t; for(int i = 0; i < w_count; ++i){ AddWord(s[i], t); } int len = msg.size(); //Begin match stack<short> pos_st; //记录匹配的字符对应msg中的位置,以便将来回溯用 short d[300]; d[len] = 0; int index = msg[len-1] - 97; if(t.child[index] && t.child[index]->end){ d[len-1] = 0; }else{ d[len-1] = 1; } for(int k = len - 2; k >= 0; --k){ index = msg[k] - 97; if(t.child[index] == NULL){ d[k] = d[k+1] +1; continue; }else{ if(t.child[index]->end){ d[k] = d[k+1]; }else{ d[k] = d[k+1] +1; } } Trie *cur; Trie *first; first = cur = t.child[index]; Trie *prev = &t; int i; pos_st.push(k); int removed = 0; while(true){ int i = pos_st.top() + 1; int next; if(prev == cur->parent){ next= NextChild(NULL, cur->child); }else{ next = NextChild(prev, cur->child); } if(next < 0){ if(cur == first){ break; }else{ i = pos_st.top(); pos_st.pop(); int recent_rmv = i - pos_st.top() -1; // 如果当前字符没有需要匹配的儿子,回退到上一字符。removed 也相应减去两个字符之间的字符。 removed -= recent_rmv; i = pos_st.top(); prev = cur; cur = cur->parent; continue; } } while(true){ if(msg[i]-97 == next){ if(cur->child[next]->end){ // 如果成功匹配了一个单词,则看remove +d[i+1]是否构成d[k]的最优解 if(removed + d[i+1] < d[k]) d[k] = removed + d[i+1]; } if(i < len -1){ prev = cur; cur = cur->child[next]; //继续匹配单词的下一个字符 pos_st.push(i++); break; }else{ int recent_rmv = i - pos_st.top() -1; //如果匹配到字串最后一个字符,则回退考察当前节点的兄弟节点 removed -= recent_rmv; prev = cur->child[next]; break; } }else{ removed++; if(removed >= d[k] | i == len -1){ //如果removed字符超过d[k],或者已经越过字串最后一个字符,则放弃匹配单词的当前字符 int recent_rmv = i - pos_st.top(); removed -= recent_rmv; prev = cur->child[next]; break; } i++; } } } } cout<<d[0]<<'\n'; } Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator