首页 > 其他分享 >UVA1401 Remember the Word

UVA1401 Remember the Word

时间:2023-06-11 11:44:23浏览次数:42  
标签:std Word Remember int next length UVA1401 end string

思路

首先有一个比较朴素的 DP 就是记 \(f_i\) 为 \(s\) 的从第 \(i\) 个字符开始到字符串结尾的划分方案数,记模板串的集合为 \(T\),\(s\) 从第 \(i\) 个字符开始到字符串结尾的子串为 \(s(i)\),那么不难写出方程:

\[f_i = \sum f_{i + \operatorname{len}(t)}[t \in T \land t 是 s(i) 的前缀] \]

初始状态为 \(f_{\operatorname{len}(s)} = 1\),表示总存在一种方法划分空串,答案即为 \(f_0\)。

但是直接按这个方程转移的话需要枚举每一个 \(t\) 还要判断 \(t\) 是否为 \(s(i)\) 的前缀,那么复杂度肯定会炸,于是考虑优化。

跟前缀有关的数据结构,不难想到字典树。把每一个 \(t\) 都插入字典树中,然后对于每一个 \(s(i)\) 直接在这棵字典树里查询 \(s(i)\) 即可,每经过一个带有结束标记的节点,就意味着找到了一个 \(t\) 是 \(s(i)\) 的前缀,然后按上边那个方程转移即可。

由于题目保证了 \(t\) 的长度不超过 \(100\),那么总的时间复杂度约为 \(O(100\operatorname{len}(s))\),已经足够好了。

代码

有一个小技巧就是在单词结束的节点内保存这个单词的长度,不过直接在查询时累加长度当然也可行。

#include <bits/stdc++.h>

using i64 = long long;

constexpr int mod = 20071027;
template<size_t SIZ = int(1e5)>
struct Trie {
  std::vector<std::vector<int>> next;
  std::vector<int> f, end;
  Trie() { next.reserve(SIZ), next.emplace_back(26), end.push_back(0); }
  void insert(const std::string &s) {
    int p = 0;
    for (int i = 0; i < s.length(); i++) {
      int d = s[i] - 'a';
      if (!next[p][d]) { 
        next.emplace_back(26), end.push_back(0);
        next[p][d] = next.size() - 1;
      }
      p = next[p][d];
    }
    end[p] = s.length();
  }
  void find(const std::string &s, int st) {
    int p = 0;
    for (int i = st; i < s.length(); i++) {
      int d = s[i] - 'a';
      if (!next[p][d]) { return; }
      p = next[p][d];
      if (end[p]) { (f[st] += f[st + end[p]]) %= mod; }
    }
  }
  int solve(const std::string &s) {
    f.clear(), f.resize(s.length() + 1), f[s.length()] = 1;
    for (int i = s.length() - 1; ~i; i--) { find(s, i); }
    return f[0];
  }
};

void solve(int id, const std::string &s) {
  int n;
  std::cin >> n;
  Trie<> trie;
  for (int i = 0; i < n; i++) {
    std::string t;
    std::cin >> t;
    trie.insert(t);
  }
  std::cout << "Case " << id << ": " << trie.solve(s) << "\n";
}

signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  std::string s;
  int cnt = 0;
  while (std::cin >> s) { solve(++cnt, s); }

  return 0;
}

标签:std,Word,Remember,int,next,length,UVA1401,end,string
From: https://www.cnblogs.com/forgot-dream/p/17472739.html

相关文章

  • 【Sword系列】第七届全国残疾人职业技能大赛样题-网络安全-特殊后门
    前言ICMP是Internet控制消息协议(InternetControlMessageProtocol)的简称,它是TCP/IP协议族的一个子协议。ICMP协议主要用于在IP网络中传递控制信息。它提供了一种在IP网络中进行错误报告、网络拓扑探测和诊断等功能的机制。通常情况下,ICMP包是由网络设备(如路由器)生成并发送给主机......
  • 去掉或修改页面底部的「动力源自 Bravada & WordPress.」字样
    打开:……/wp-content/themes/bravada/includes/core.php定位至位于第400行左右的「bravada_master_footer」处;做相应修改。参考:https://blog.csdn.net/qq_45790384/article/details/127335865......
  • Python+pywin32批量转换Word文件为PDF文件
    代码功能:把当前文件夹中多个Word文件批量转换为PDF文件技术原理:代码实际上是调用了Word的“导出”功能,模拟了手工转换的操作并实现了自动化,要求已正确安装Python扩展库pywin32和Office2007以上版本。......
  • 【Sword系列】第七届全国残疾人职业技能大赛样题-网络安全-数据包里有甜甜圈哦~
    前言Wireshark(前称Ethereal)是一个网络数据包分析软件。网络数据包分析软件的功能是截取网络数据包,并尽可能显示出最为详细的网络数据包数据。在过去,网络数据包分析软件是非常昂贵,或是专门属于营利用的软件,Wireshark的出现改变了这一切。在GNU通用公共许可证的保障范围底下,用户可以......
  • Python实现Excel与Word文件中表格数据的导入导出
    问题描述:Excel文件“测试文件.xlsx”中有3个worksheet,每个worksheet中的行数和列数都不相同,要求把这3个worksheet中的数据导入到一个Word文件中,每个worksheet生成一个单独的表格,每个表格的样式不同。在Excel和Word之间,是支持表格直接复制的,如果数量少,可以直接复制,如果多的话,可以参......
  • Python控制Word文件中段落格式与文本格式
    本文主要介绍扩展库python-docx中关于Word文件中文本格式控制的接口和用法,可以使用命令pipinstallpython-docx安装,然后通过名字docx来使用其中提供的功能。1、设置段落格式段落是Word中的一个块级对象,在其所在容器的左右边界内显示文本,当文本超过右边界时自动换行。段落的边界通......
  • 使用Python检查实验教学大纲(Word文件)中前后信息是否一致
    问题描述:应选用教材的老师们要求,整理了一份与教材《Python程序设计(第3版)》配套的实验教学大纲,共45页72个实验项目。需要的老师可以联系董老师获取这个文件。在实验教学大纲中,核心内容有两块,一个是实验项目信息汇总表,部分内容如下图所示,实验教学大纲中第二个核心内容是每个实验项目......
  • 【Sword系列】第七届全国残疾人职业技能大赛样题-网络安全-数据包分析
    前言Wireshark(前称Ethereal)是一个网络数据包分析软件。网络数据包分析软件的功能是截取网络数据包,并尽可能显示出最为详细的网络数据包数据。在过去,网络数据包分析软件是非常昂贵,或是专门属于营利用的软件,Wireshark的出现改变了这一切。在GNU通用公共许可证的保障范围底下,用户可以......
  • Python提取Word文档中所有脚注文本
    问题描述:提取Word文档中所有脚注文本,适用于doc和docx格式。测试文件:需要的扩展库:pywin32,如果使用Anaconda3Spyder的话,默认安装了这个扩展库,不需要额外安装。参考代码:运行结果:---董付国老师Python系列图书---友情提示:不建议购买太多,最好先通过京东、当当、天猫查阅图书了解目录和......
  • 使用Kmeans对Word2vec的输出做聚类
    Word2vec会产出每个词语的权重向量使用这个向量,可以直接对所有的词语聚类以下代码,以word2vec的model作为输入,进行kmeans训练,同时进行K的迭代计算,选出WSSSE最小的K值Scala *将word2vec的结果,作为kmeans的输入进行聚类;进行K的多次迭代,选出WSSSE最小的K*@paramspark......