• UVA1401 Remember the Word


    刘汝佳新书--训练指南

    题意:给出N个不同单词和一个长字符串S。把这个字符串分解成若干个单词的连接(单词尅重复使用),问有多少种方法?

    分析:令d[i]表示从字符i开始的字符串的分解方案数,则dans[i]=sum{dans[i+d[x]] | 单词x是S[i...len]的前缀};

    // File Name: 1401.cpp
    // Author: zlbing
    // Created Time: 2013/3/14 18:55:52
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,n) for(int i=0;i<n;i++)
    #define REP1(i,n) for(int i=1;i<n+1;i++)
    const int maxnode=4000*100+10;
    const int sigma_size=26;
    
    // 字母表为全体小写字母的Trie
    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'; } // 字符c的编号
    
      // 插入字符串s,附加信息为v。注意v必须非0,因为0代表“本结点不是单词结点”
      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;  // 中间结点的附加信息为0
            ch[u][c] = sz++; // 新建结点
          }
          u = ch[u][c]; // 往下走
        }
        val[u] = v; // 字符串的最后一个字符的附加信息为v
      }
      void find_prefix(char *s,int len,vector<int>& ans){
         // int len=strlen(s);每次找前缀时都算一次长度,要算10^5次,因此导致超时了。。。又这长度是有规律的,因此可以事先算出来
          int u=0;
          for(int i=0;i<len;i++){
              if(s[i]=='\0')break;
            int c=idx(s[i]);
            if(ch[u][c]){
                u=ch[u][c];
                if(val[u])ans.push_back(val[u]);
            }else break;
          }
      }
    };
    Trie solver;
    char str[300050];
    int d[4005];
    int dans[300050];
    const int MOD=20071027;
    int main(){
        int cas=0;
        while(~scanf("%s",str)){
            int n;
            scanf("%d",&n);
            solver.clear();
            char word[105];
            REP1(i,n){
                scanf("%s",word);
                int len=strlen(word);
                d[i]=len;
                solver.insert(word,i);
            }
            int len=strlen(str);
            CL(dans,0);
            dans[len]=1;
            for(int i=len-1;i>=0;i--){
                vector<int> ans;
                solver.find_prefix(str+i,len-i,ans);
                for(int j=0;j<ans.size();j++){
                    dans[i]=(dans[i]+dans[i+d[ans[j]]])%MOD;
                }
            }
            printf("Case %d: %d\n",++cas,dans[0]);
        }
        return 0;
    }
  • 相关阅读:
    BUAA2020个人博客作业小结
    BUAA2020软工热身作业小结
    个人博客作业----总结
    个人阅读作业7
    超链接按钮点击变色,原来的链接恢复原色
    setInterval和setTimeout的区别以及setInterval越来越快问题的解决方法
    自定义网站404页面
    jQuery实现的上下滚动公告栏详细讲解
    K先生的博客
    Bootstrap4响应式布局之栅格系统
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2960260.html
Copyright © 2020-2023  润新知