题解 UVA1401 【Remember the Word】

题目链接:Link

Solution

第一次写Trie,写篇题解纪念一下......

令d(i)表示从字符i开始的字符串(即后缀 S[i...L-1])的分解方案数,则d(i)=sum{d(i+len(x)) | 单词x是 S[i...L-1]的前缀}。

显然,关键点就在判断前缀上。可以把所有的单词组织成Trie,然后试着在Trie中查找S[i...L-1],每找到一个单词节点,就状态转移一次....

#include<cstdio>
#include<cstring>
const int mod=20071027;
const int maxL=300000;
int L,S,d[maxL+5],kase;
char str[maxL+5],tmp[105];
const int maxnode=4000*105;//注意开大一点
const int sigma_size=26;
struct Trie
{
int ch[maxnode][sigma_size];
bool val[maxnode];
int sz;
Trie() { sz=1; }
inline void clear()
{
sz=1;
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));//一次性赋值
}
inline void insert(char *s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int c=s[i]-'a';
if(!ch[u][c])
ch[u][c]=sz++;//申请新节点
u=ch[u][c];
}
val[u]=1;
}
}trie;
int main()
{
#ifdef local
freopen("pro.in","r",stdin);
#endif
while(scanf("%s",str)==1)
{
L=strlen(str);
scanf("%d",&S);
memset(d,0,sizeof(d));
trie.clear();
for(int i=0;i<S;i++)
{
scanf("%s",tmp);
trie.insert(tmp);
}
d[L]=1;//边界
for(int i=L-1;i>=0;i--)
for(int j=0,u=0;i+j<L&&trie.ch[u][str[i+j]-'a'];j++)
{
u=trie.ch[u][str[i+j]-'a'];
if(trie.val[u]) d[i]=(d[i]+d[i+j+1])%mod;
//状态转移
}
printf("Case %d: %d\n",++kase,d[0]);
}
return 0;
}
posted @   happyZYM  阅读(143)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
点击右上角即可分享
微信分享提示