例题3.11 背单词 LA3942

来源:互联网 发布:2017下半年网络流行词 编辑:程序博客网 时间:2024/06/06 09:08

1.题目描述:点击打开链接

2.解题思路:本题利用Trie+dp解决。首先,令d(i)表示从字符i开始的字符串(即后缀S[i...L])的分解方案数,那么d(i)=d(i+len(x)|单词x是S[i..L]的前缀)。如果我们枚举单词,然后判断它是否为S[i...L]的前缀,时间无法承受。所以可以考虑事先把所有的单词存入Trie,然后试着在Trie中查找S[i...L]。查找时,如果找到了一个单词结点,就把它的序号记下来,这样就找到了一个单词x,最多只需要100次比较就能找到所有的x。

3.代码:

#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<functional>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define me(s)  memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)typedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, int> P;const int maxnode = 4000 * 100 + 10;const int sigma_size = 26;struct Trie{  int ch[maxnode][sigma_size];  int val[maxnode];  int sz;  void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }  int idx(char c) { return c - 'a'; }  void insert(const char *s, int v)  {    int u = 0, n = strlen(s);    for(int i = 0; i < n; 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;  }  void find_prefixes(const char *s, int len, vector<int>& ans)  {    int u = 0;    for(int i = 0; i < len; i++)    {      if(s[i] == '\0') break;      int c = idx(s[i]);      if(!ch[u][c]) break;      u = ch[u][c];      if(val[u] != 0) ans.push_back(val[u]);    }  }};#include<cstdio>const int maxl = 300000 + 10; // 文本串最大长度const int maxw = 4000 + 10;   // 单词最大个数const int maxwl = 100 + 10;   // 每个单词最大长度const int MOD = 20071027;int d[maxl], len[maxw], S;char text[maxl], word[maxwl];Trie trie;int main(){  int kase = 1;  while(scanf("%s%d", text, &S) == 2)    {        trie.clear();        for(int i = 1; i <= S; i++)        {            scanf("%s", word);            len[i] = strlen(word);            trie.insert(word, i);        }        memset(d, 0, sizeof(d));        int L = strlen(text);        d[L] = 1;        for(int i = L-1; i >= 0; i--)        {            vector<int> p;            trie.find_prefixes(text+i, L-i, p);            for(int j = 0; j < p.size(); j++)                d[i] = (d[i] + d[i+len[p[j]]]) % MOD;        }        printf("Case %d: %d\n", kase++, d[0]);    }    return 0;}

0 0
原创粉丝点击