【LA3942-Remember the word 】Trie
http://acm.hust.edu.cn/vjudge/problem/22109
题意:给定n个单词,一个字符串,问把这个字符串划分为若干个单词的连接(单词可重复使用)有多少种方案(mod20071027)。
题解:
设d[i]为从第i个字母开始的后缀有多少种匹配方案。
if 单词x是当前后缀的前缀: d[i]=sum{d(i+len(x))}
用所有单词建一棵trie,从后往前循环i,对于每一个i进入trie查找前缀,更新d[i]。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; const int L=300100,Mod=20071027; char s0[L],s[L]; int n,num; int d[L],ch[L][30],bk[L]; void insert(char *c) { int l=strlen(c); int x=0; for(int i=0;i<l;i++) { int id=c[i]-'a'+1; if(!ch[x][id]) { num++; ch[x][id]=num; } x=ch[x][id]; } bk[x]=l; } void find(int l,int r) { int x=0; for(int i=l;i<=r;i++) { int id=s0[i]-'a'+1; if(!ch[x][id]) break; x=ch[x][id]; if(bk[x]) d[l]=(d[l]+d[l+bk[x]])%Mod; } } //d[i]=sum(d[i]+len(x)) int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T=0; while(scanf("%s",s0)!=EOF) { num=0; memset(bk,0,sizeof(bk)); memset(ch,0,sizeof(ch)); memset(d,0,sizeof(d)); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s); insert(s); } int l=strlen(s0); d[l]=1; for(int i=l-1;i>=0;i--) find(i,l-1); // for(int i=0;i<l;i++) printf("%d ",d[i]);printf("\n"); printf("Case %d: %d\n",++T,d[0]%Mod); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端