UVALive 3942 Remember the Word(字典树+DP)
生活随笔
收集整理的這篇文章主要介紹了
UVALive 3942 Remember the Word(字典树+DP)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1943
題意:一個長字符串和多個短字符串,求短字符串有多少種方式組成長字符串。
狀態(tài)轉移方程: dp[i] = sum(d[i + len(x)]) ?(x是s[i...L]的前綴)?
對于每個i,如果直接暴力尋找s[i...L]的前綴,復雜度為O(nm) (n為短字符串的個數(shù),m為短字符串的長度),肯定會超時。
既然是求前綴,那么可以使用前綴樹(字典樹)來解決此問題。用字典樹尋找前綴的復雜度為O(m)。
#include <cstdio> #include <iostream> #include <cstring> #define maxn 400100 #define maxm 300010 #define mod 20071027 #define sigma_size 26 using namespace std;char str[maxm], tstr[110]; int dp[maxm], ch[maxn][sigma_size], val[maxn], sz;struct Trie {int get_id(char c){return c - 'a';}void insert(char* str, int v){int u = 0, len = (int)strlen(str);for (int i = 0; i < len; ++i){int id = get_id(str[i]);if (!ch[u][id]){memset( ch[sz], 0, sizeof(ch[sz]));val[sz] = 0;ch[u][id] = sz++;}u = ch[u][id];}val[u] = v;}int query(char* str, int start){int u = 0, result = 0, len = (int)strlen(str), next;for (int i = 0; i < len; ++i){int id = get_id(str[i]);next = ch[u][id];if (next){if (val[next])result = (result + dp[i + start + 1])%mod;}elsebreak;u = next;}return result;} };void init();int main(void) {int ca = 1, n;while (scanf("%s", str) != EOF){init();int len = (int)strlen(str);scanf("%d", &n);Trie trie = Trie();while (n--){scanf("%s", tstr);trie.insert( tstr, 1);}dp[len] = 1;for (int i = len - 1; i >= 0; i--){dp[i] = trie.query( str + i, i);}printf("Case %d: %d\n", ca++, dp[0]);}return 0; }void init() {sz = 1;memset( dp, 0, sizeof(dp));memset( ch[0], 0, sizeof(ch[0]));memset( val, 0, sizeof(val)); }?
轉載于:https://www.cnblogs.com/chuninsane/p/4923533.html
總結
以上是生活随笔為你收集整理的UVALive 3942 Remember the Word(字典树+DP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浮动导航
- 下一篇: thinkphp 第二节