UVALive 3942 Trie加速dp
参考http://blog.csdn.net/qq_24489717/article/details/50832001
Trie树模板题
Trie树很好的把子串重复部分利用起来,一遍遍历可以用到多个单词节点的信息
转移方程:DP[i]=sum{DP[i+len(x)] | x为S[i……L]的前缀}
从小到大枚举原串后缀S
在Trie树中匹配后缀串,每到达一个单词节点就让DP【S】加上【从单词节点开始的后缀的DP值】
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=4e5+7; const int size=26; const int mod=20071027; char ori[maxn]; char tmp[200]; int dp[maxn]; int ch[maxn][size]; int val[maxn]; struct trie{ int sz; trie(){sz=1;memset(ch,0,sizeof(ch));} int idx(char c){return c-'a';} void insert(char *s,int v){ int u=0;int n=strlen(ori); for(int i=0;s[i];i++){ int c=idx(s[i]); if(!ch[u][c]){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; } int find(char *s,int pos){ int ans=0; int u=0;int n=strlen(s); for(int i=pos;i<n&&i<=pos+100;i++){ int c=idx(s[i]); if(!ch[u][c])return ans; u=ch[u][c]; if(val[u])ans=(dp[i+1]+ans)%mod; } return ans; } }tree; int main(){ int n,kase=0; while(~scanf("%s",ori)){ tree=trie(); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s",tmp); tree.insert(tmp,1); } int len=strlen(ori); dp[len]=1; for(int i=len-1;i>=0;i--){ dp[i]=tree.find(ori,i); } printf("Case %d: %d\n",++kase,dp[0]); } return 0; }