1、前言

  这是我出的第一套题目,话说感觉有点晚了,还是在向总安排下出的。我被安排的是字符串方面的内容,这应该相对而言是比较小众的知识点吧,但是一样的有作用的,也有很神的题目。所谓是NOIP模拟题,其实只有两道题是在NOIP范围内的,但是要说很难的话,我觉得也不至于(可能是站在出题人的角度上吧)。

  因为是第一次出题目,效率确实不怎么高,相比学长出题一天就是一套,我这一套出了快十天了,内容和数据是原创的,但是难免有模板题的感觉(毕竟不能太过头),除了部分出题思路有所参照之外。

2、Tea 喝茶

大概题意: 给出n个字符串,求有多少个字符串中的Q/W/E/R个数超过该字符串的字符个数的1/2。

题解:

  由于我们要进行的操作就是查找字符串中的特殊字符,所以最简单有效的方法就是对于每一个字符串的每一个字符进行枚举,统计这个字符串中的Q/W/E/R个数,然后用该个数乘2看是否超过字符串总长度,求和即可。需要注意的是,由于大小写字母均存在,但是不区分,故需要进行两次判断或者进行大小写转化后再统计。时间复杂度为O(n∗len)  ,其中len为所有字符串长度的平均值。

但是我们注意到,对于100%的数据,1≤n≤2000,字符串长度≤20000,题目的复杂度很高,一旦程序的常数写得过大,是很容易超时的。

3、Journey 归途

大概题意:给出一个长度为n的带权字符串和长度为m的子字符串,求子字符串是否出现在带权字符串中,且出现位置的最后一位之前的权值和是否超过限制权值,如果没有就输出该权值和。存在x组数据。

题解:

  题目表面上似乎是一道图论题,n个节点,m条边,并且还带权值,但是所询问内容令人费解:在图中找到一段路。如果题目要求每个节点只能访问一次,这样当然是简单的,但是由于不限制次数,故可能出现若干个环,并且对于每一条边,每次经过的权值都是不同的!如果直接用无向图来维护的话,基本上是不可能的。所以,我们可以从另外一个角度来考虑:我们将所走的这段路铺平,不将其视为图中遍历,而是看作一个线性数组,而题目要求为在这个数组中找到另一个线性数组。这样,题意就已经很明确了:子串匹配母串。(即大概题意所述)

确定了字符串匹配这个大主题,直接想到的就是暴力枚举,时间复杂度为O(x∗n∗m)。根据题目所给数据范围,这显然是不能通过的。KMP算法可以很好地解决,时间复杂度为O(x∗(n+m))。当然扩展KMP算法也可行。

  由于权值的存在以及对其的限制,我们只需要记录字符串中每个字符之前的权值之和,对于第一次成功匹配判断是否大于maxt,如果是的,则说明无法匹配上;相反地,直接输出权值和。

  要注意到的是,由于2≤p≤m≤10^5,  1≤t[i]≤10^5,0≤maxt≤∑t×2,故超过int范围是不可避免的,所以需要开long long。

4、Piano 钢琴手

大概题意:给出一个带n个字符的字典,有m个禁用的单词,问能组成多少个不同的长度为m的字符串,不包括p个禁用的单词。如果不存在则输出-1。

题解:

  n个字符,组成长度为m的字符串,假设我们无视那k个禁用单词的情况,那么情况为多少呢?其实就是个简单的数学问题,方案数为n^m。其实这样已经可以得到10分了!我们注意到,在数据点7-8中,由于每一个有问题的音乐片段长度和所弹奏长度相等,这样的话每禁止一个,方案数直接减1即可,即答案为n^m−k。

  那么对于其他情况的话,不能简单的用公式来计算。首先可以确定的是,我需要构建AC自动机,将题目要表达的意思形象化。因为单词的禁用,不仅影响到其本身,而且只要一段之中有这个单词,就都算不合法,那么我们将这p个禁用的单词放入AC自动机中,设单词的最后一个字符的节点为i,则节点i的所有儿子节点就都不合法了。这也同样意味着,对于两个字符串a和b,如果a是b的前缀,那么禁用b是可以忽略的(想一想,为什么)。如图所示,假设给出一个字符集合为{a,b,c}的字典,禁用单词为:a,bb。则构建的AC自动机如下:

  紫色表示插入AC自动机的禁用单词,灰色和紫色部分都是不可选的,而剩下的橙色的个数之和就是方案数了。

  然而接下来就是如何计算方案数了。这里建议用简单方便的动态规划,用f[i][j]表示当前长度为i,字符为j的方案数。状态转移也非常简单:

    f[i][j]=∑f[i−1][j],k表示能够在AC自动机中走到字符为j的节点的节点。

  一切似乎都已经准备就绪,但是我们再来看一眼数据范围,当n=25,m=50时,答案最大可能高达25^50=7.89e+69,所以最后计算的时候,需要进行高精度运算。

5、Happiness 幸福

大概题意:给出n个字符串,找出最长公共子串,要求在每个字符串中都出现至少两次,并且没有重叠。

题解:

  首先可以确定的是,单串匹配多串首选后缀数组。相比直接找最长公共子串,这道题附加的条件在于每个字符串内都要出现多次,且不重叠,那么暂时先不管,考虑如何求最长公共子串。

  因为需要的是在每个字符串中都出现,我们显然不可能为每一个字符串都开一个后缀数组,这样操作麻烦,又浪费空间。可以考虑将所有的字符串全部连在一起,中间用特殊符号中断以区分。但是题意中写明了所有可见的字符都有可能出现,我们不能保证哪一个特殊符号不会在字符串中出现,所以可以考虑用一个标号数组进行区分,即num[i]表示第i个后缀在第num[i]个字符串中。

  利用后缀数组,我们将每个后缀的名次计算出来,然后再计算相邻后缀的最长公共前缀,即height[i]。

  现在考虑每个字符串内部需要出现多次的条件。其实在看明白了前面如何衔接不同字符串这个步骤之后,这就很好去写了,即将原来字符串之间的最长公共前缀修改成每个字符串内部的最长公共前缀。求解的过程用二分答案来完成,每次记录所有字符串内部一个位置的最大值和一个位置的最小值,观察差值,求出所有答案的最大值即可。

Test of String的更多相关文章

  1. 透过WinDBG的视角看String

    摘要 : 最近在博客园里面看到有人在讨论 C# String的一些特性. 大部分情况下是从CODING的角度来讨论String. 本人觉得非常好奇, 在运行时态, String是如何与这些特性联系上的 ...

  2. JavaScript String对象

    本编主要介绍String 字符串对象. 目录 1. 介绍:阐述 String 对象的说明以及定义方式. 2. 实例属性:介绍 String 对象的实例属性: length. 3. 实例方法:介绍 St ...

  3. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

  4. [C#] string 与 String,大 S 与小 S 之间没有什么不可言说的秘密

    string 与 String,大 S 与小 S 之间没有什么不可言说的秘密 目录 小写 string 与大写 String 声明与初始化 string string 的不可变性 正则 string ...

  5. js报错: Uncaught RangeError: Invalid string length

    在ajax请求后得到的json数据,遍历的时候chrome控制台报这个错误:Uncaught RangeError: Invalid string length,在stackoverflow查找答案时 ...

  6. c# 字符串连接使用“+”和string.format格式化两种方式

    参考文章:http://www.liangshunet.com/ca/201303/218815742.htm 字符串之间的连接常用的两种是:“+”连接.string.format格式化连接.Stri ...

  7. 【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed

    之前以为BinaryWriter写string会严格按构造时指定的编码(不指定则是无BOM的UTF8)写入string的二进制,如下面的代码: //将字符串"a"写入流,再拿到流的 ...

  8. JavaScript中String对象的方法介绍

    1.字符方法 1.1 charAt() 方法,返回字符串中指定位置的字符. var question = "Do you like JavaScript?"; alert(ques ...

  9. 在多线程编程中lock(string){...}隐藏的机关

    常见误用场景:在订单支付环节中,为了防止用户不小心多次点击支付按钮而导致的订单重复支付问题,我们用 lock(订单号) 来保证对该订单的操作同时只允许一个线程执行. 这样的想法很好,至少比 lock( ...

  10. BCL中String.Join的实现

    在开发中,有时候会遇到需要把一个List对象中的某个字段用一个分隔符拼成一个字符串的情况.比如在SQL语句的in条件中,我们通常需要把List<int>这样的对象转换为“1,2,3”这样的 ...

随机推荐

  1. Harmonious Army

    Harmonious Army Now, Bob is playing an interesting game in which he is a general of a harmonious arm ...

  2. 剑指offer 栈的压入和弹出

    题目描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈 ...

  3. python 进程和线程-线程和线程变量ThreadLocal

    线程 线程是由若干个进程组成的,所以一个进程至少包含一个线程:并且线程是操作系统直接支持的执行单元.多任务可以由多进程完成,也可由一个进程的多个线程来完成 Python的线程是真正的Posix Thr ...

  4. C++ OpenSSL 之二:生成RSA文件

    1.等同于生成private key: openssl genrsa -out "save_path" 2048 2.代码如下 bool MakeRsaKeySSL(const c ...

  5. 机器学习之KMeans聚类

    零.学习生成测试数据 from sklearn.datasets import make_blobs from matplotlib import pyplot # create test data ...

  6. c#执行sql超时

    超时分为多种,SqlConnection有超时选项, SqlDataAdapter也有超时选项设置如下: SqlConnection:就用链接字符串给予的Timeout设置就行单位秒: SqlData ...

  7. Linux shell if条件判断2

    前面介绍linux shell的if判断的语法,现在再补充一点. Linux shell if条件判断1 分支判断结构     if , case   下面两个结构语法,已经在前面有过示例. 结构1: ...

  8. Firefox火狐浏览器打开新标签页一直闪烁

    问题:Firefox浏览器打开新标签页一直刷新,不能打开页面 解决办法:在url栏输入about:support,打开配置文件夹,然后删除目录中包含storage所有文件,重启Firefox即可.

  9. Linux上搭建SVN服务

    环境:centos7 一.搭建svn服务 1. 安装svn yum -y install subversion 2. 创建一个目录作为svn服务的地址(svn://192.168.0.2:3690 访 ...

  10. 【IOS】libimobiledevice常用命令

    libimobiledevice 是一个跨平台的软件库,支持 iPhone®, iPod Touch®, iPad® and Apple TV® 等设备的通讯协议.   安装 命令: brew ins ...