(trie)UVALive - 3942 Remember the Word

题目链接

设d[i]表示从下标i的字符开始的字符串的分解方法数,显然有倒序的递推公式。

需要求每个位置开始是否能组成模式串的前缀,才可以建立正确的递推。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <vector>
 12 #include <stack>
 13 #define mp make_pair
 14 #define MIN(a,b) (a>b?b:a)
 15 #define rank rankk
 16 //#define MAX(a,b) (a>b?a:b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int MAX=3e5+5;
 20 const int INF=1e9+5;
 21 const int B=1024;//桶的大小
 22 const double M=4e18;
 23 const int MAX_NODE=MAX;
 24 const int sigma_size=30;
 25 using namespace std;
 26 //const int MOD=1e9+7;
 27 const int MOD=20071027;
 28 typedef pair<int,int> pii;
 29 const double eps=0.000000001;
 30
 31 struct Trie
 32 {
 33     int ch[MAX_NODE][sigma_size];//点数、“字母”数
 34     int val[MAX_NODE];
 35     int num;//结点总数
 36     Trie(){num=1;memset(ch[0],0,sizeof(ch[0]));}//初始时仅有根节点
 37     void clear() { num = 1; memset(ch[0], 0, sizeof(ch[0])); }
 38     int idx(char c)//返回对应字符的编号
 39     {
 40         return c-‘a‘;
 41     }
 42     /*
 43         插入字符串s,附加信息为v。注意v必须非0,因为0代表:本结点不是单词结点
 44     */
 45     void insert(const char *s,int v)
 46     {
 47         int u=0,len=strlen(s);
 48         for(int i=0;i<len;i++)
 49         {
 50             int c=idx(s[i]);
 51             if(!ch[u][c])//结点不存在
 52             {
 53                 memset(ch[num],0,sizeof(ch[num]));
 54                 val[num]=0;//中间节点的附加信息为0
 55                 ch[u][c]=num++;//新建结点
 56             }
 57             u=ch[u][c];//往下走
 58         }
 59         val[u]=v;//字符串的最后一个字符的附加信息为v
 60     }
 61     /*
 62      查询字符串的“附加信息”
 63      查询过程中间中断返回0
 64     */
 65     int check(char *s)
 66     {
 67         int u=0,len=strlen(s);
 68         for(int i=0;i<len;i++)
 69         {
 70             int c=idx(s[i]);
 71             if(!ch[u][c])
 72                 return 0;
 73             u=ch[u][c];
 74         }
 75         return val[u];
 76     }
 77     /*
 78     找字符串s的长度不超过len的前缀
 79     */
 80     void find_prefixes(const char *s,int len,vector <int> &ans)
 81     {
 82         int u=0;
 83         for(int i=0;i<len;i++)
 84         {
 85             if(s[i]==‘\0‘)
 86                 break;
 87             int c=idx(s[i]);
 88             if(!ch[u][c])
 89                 break;
 90             u=ch[u][c];
 91             if(val[u]!=0)//过程中所有找到的全都push进去
 92                 ans.push_back(val[u]);
 93         }
 94     }
 95 };
 96 char a[MAX];
 97 int s,d[MAX],len,siz[MAX],cnt;
 98 Trie dic;
 99 char tem[MAX];
100 vector <int> an;
101 int main()
102 {
103     while(~scanf("%s",a))
104     {
105         dic.clear();
106         an.clear();
107         scanf("%d",&s);
108         for(int i=1;i<=s;i++)
109         {
110             scanf("%s",tem);
111             siz[i]=strlen(tem);
112             dic.insert(tem,i);
113         }
114         memset(d,0,sizeof(d));
115         len=strlen(a);
116         d[len]=1;
117         for(int i=len-1;i>=0;i--)
118         {
119             an.clear();
120             dic.find_prefixes(a+i,len-i,an);
121             for(int j=0;j<an.size();j++)
122             {
123                 d[i]=(d[i]+d[i+siz[an[j]]])%MOD;
124             }
125         }
126         printf("Case %d: %d\n",++cnt,d[0]);
127     }
128 }
时间: 2024-10-17 11:55:45

(trie)UVALive - 3942 Remember the Word的相关文章

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie) ACM 题目地址: UVALive 3942 - Remember the Word 题意: 给一些单词,然后给一个长的单词,问有几种方法能组成这个大单词,单词可以重复用. 分析: DP[i]=sum{DP[j} (i<j<len),从后往前求. 本来用数组Trie写得爽爽的,1A了. 发现2s多,不能忍! 然后用指针Trie写了一遍,各种出错,整个人都不好了... 研究了一遍别人代码,发现快

UVALive - 3942 - Remember the Word (Trie树)

UVALive - 3942 Remember the Word Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a p

UVALive - 3942 Remember the Word[Trie DP]

UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Know- ing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remem

【暑假】[实用数据结构]UVAlive 3942 Remember the Word

UVAlive 3942 Remember the Word 题目: Remember the Word Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Know

UVALive 3942 Remember the Word 字典树+dp

/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5)和m个单词(每个单词长度最多100).单词都是不同的.该字符串可以由若干个单词组成,问最多有多少种组合方式. 思路:字典树+dp 用字典树处理好m个单词,定义dp[i]表示从i开始的字符串可以由单词组成的方式数. 那么dp[i] += dp[i+j]; j表示某个单词和字符串的[i,i+j-1]匹配

UVALive - 3942 Remember the Word[树状数组]

UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device with a variable electric resistance. It has two terminals and some kind of control mechanism (often a dial, a wheel or a slide) with which the resistance

HDU 1247 Hat&#39;s words(Trie)

HDU 1247 Hat's words(Trie) ACM 题目地址: HDU 1247 Hat's words 题意: 给些单词,问每个单词是否能用另外两个单词拼出. 分析: 直接保存到trie里面,然后暴力切割查询即可. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: 1247.cpp * Create Date: 2014-09-24 11:04:11 * Descripton: */ #include <cstdio

UVA 3942 - Remember the Word (Trie)

3942 - Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can't remember number

LA3942-Remember the Word(Trie)

题意: 有s个不同的单词,给出一个长字符串把这个字符串分解成若干个单词的连接(可重复使用),有多少种分解方法 分析: dp[i]表示i开始的字符串能分解的方法数 dp[i]=sum(dp[i+len(x)]);单词x是i开始的字符串的前缀. #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #