LA 3942Remember the Word
设d(i)为从字符i开始的字符串的分解方案数,则d[i]= sum{(d[i]+len(x))}
x 为 d[i]代表的字符的前缀
/* * @Author: CY__HHH * @Date: 2020-09-04 00:56:59 * @LastEditTime: 2020-09-05 12:50:19 */ #include<bits/stdc++.h> //树上DP Trie #define rep(i, n) for(int i=0;i!=n;++i) #define per(i, n) for(int i=n-1;i>=0;--i) #define Rep(i, sta, n) for(int i=sta;i!=n;++i) #define rep1(i, n) for(int i=1;i<=n;++i) #define per1(i, n) for(int i=n;i>=1;--i) #define Rep1(i, sta, n) for(int i=sta;i<=n;++i) #define L rt<<1 #define R rt<<1|1 #define inf (0x3f3f3f3f) #define llinf (1e18) #define ALL(A) A.begin(),A.end() #define SIZE(A) ((int)A.size()) #define MOD (20071027) #define PII pair<int,int> typedef long long i64; using namespace std; const int maxn = 2e6 + 32; int Trie[maxn][26]; int total; int dp[maxn]; bool vis[maxn];//judge是否为单词 void insert(string &str){ int root = 0; for(auto &c:str){ int pos = c - 'a'; if(!Trie[root][pos]) Trie[root][pos] = ++total; root = Trie[root][pos]; } vis[root] = true;//当前节点为单词标记 } void find(string str,int p){// p为当前位置 int root = 0; for(int i=0;i!=(int)str.size();++i){ int pos = str[i] - 'a'; if(!Trie[root][pos]) return;//如果任何一个前缀都不存在 root = Trie[root][pos]; if(vis[root])//每一个单词前缀即为递推式 dp[p] = (dp[p] + dp[p + i + 1]) % MOD; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string text; cin >> text; int s; string temp; cin >> s; for(int i=0;i!=s;++i){ cin >> temp; insert(temp); } int len = text.size(); dp[len] = 1;//dp界限 for(int i=len-1;i>=0;--i) find(text.substr(i),i); cout << dp[0] << endl; return 0; }
不怕万人阻挡,只怕自己投降。
posted on 2020-09-05 12:55 chengyulala 阅读(99) 评论(0) 编辑 收藏 举报