码迷,mamicode.com
首页 > 其他好文 > 详细

例题3.11 背单词 LA3942

时间:2015-08-28 00:54:11      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:trie   dp   

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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

例题3.11 背单词 LA3942

标签:trie   dp   

原文地址:http://blog.csdn.net/u014800748/article/details/48038299

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!