首页 > 代码库 > UVALive 3942 Remember the Word
UVALive 3942 Remember the Word
空降链接:https://vjudge.net/problem/UVALive-3942
题意:
给出一个字符串s(strlen(s)<=3e5)和一堆字符串str[MAX](MAX<=4000,strlen(str[i])<=100),每个str[i]可以用无限次,求用str这些字符串拼接成s的方案数。
题解:
根据题意肯定要先建棵trie。。。然后开始xjbDP了。因为每个串的长度都<=100,所以每次可以枚举s的下标i作为起始坐标,在字典树中找当前下标为起点的前缀,如果在与字典树匹配中的某些串的结束位置与当前的s中的下标j匹配那么dp[j]+=dp[i-1]*tree[pos].ends。当然了,dp[0]=1,我的文本串的起始下标是1;
#include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long LL; const double eps = 1e-10; const int maxn = 300000 + 100; const int mod=20071027; char ss[maxn],s[4005]; int n,dp[maxn],tt=0; struct Trie { struct Tree { int c[26]; int cc,ends; long long ans=0; }tree[4000*100+100]; int cnt; long long ans; void init() {memset(tree,0,sizeof(tree)); cnt=ans=0;} void build(int pos,int x) {tree[pos].c[x]= ++cnt;} void insert(char* str) { int len=strlen(str),pos=0,ch; for(int i=0;i<len;++i) { ch=str[i]-‘a‘; if(!tree[pos].c[ch])build(pos,ch); pos=tree[pos].c[ch]; tree[pos].cc++; } tree[pos].ends++; } void solve(char* str,int llen) { for(int i=1;i<=llen;++i) { int pos=0,ch=str[i]-‘a‘,pp=i; while(tree[pos].c[ch]&&pp<=llen) { pos=tree[pos].c[ch]; if(tree[pos].ends) { (dp[pp]+=(dp[i-1]*tree[pos].ends)%mod)%=mod; } pp++; ch=str[pp]-‘a‘; } } } }trie; int main() { #ifdef ac freopen("in.txt" , "r" , stdin); // freopen("out.txt" , "w" , stdout); #endif while(~scanf("%s",ss+1)) { trie.init(); int llen=strlen(ss+1); scanf("%d",&n); while(n--) scanf("%s",s),trie.insert(s); memset(dp,0,sizeof(dp)); dp[0]=1; trie.solve(ss,llen); printf("Case %d: %d\n",++tt,dp[llen]); } return 0; }
UVALive 3942 Remember the Word
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。