CF 494B 【Obsessive String】
很有趣的一道题
这道题提议很难懂,其实就是让你求合法的集合数目。合法的集合定义为:
1、集合中的所有串都是s的子串,且互不重叠 2、集合中的所有串都含有子串t。
看到网上很多题解说要用kmp,但我就不用...
因为仅需进行一个字符串匹配,而hash是很好写的匹配啊
而且kmp的next指针在dp中并没有起到作用。
说一下主体思路吧:
设两个字符串为s,t,长度分别为l1,l2
首先我们在原串中查找所有的位置i,使s中以i为结尾的子串与t匹配
对于所有的位置i,标记flag[i]=1;
然后我们进行dp
设dp[i]表示以选取的所有集合中集合的最后一个元素的结尾均为i,开头为j(j不体现在状态中,1<=j<=i-l2+1)的所有方案数
那么答案就是∑(i=1~l1)dp[i]
接下来我们考虑转移
首先,对于某一位置,如果flag[i]=0,我们有:
dp[i]=dp[i-1]
原因:如果到这一位置没有匹配上,那么说明这个位置只能被包含在前一个状态中。
那么,如果flag[i]=1,怎么办?
我们考虑集合中元素的个数:
如果只有一个元素,那么由于flag[i]=1,说明i-l2+1~i与t是可以完全匹配的,所以从1到i-l2+1都可以作为这个元素的起点,所以方案数为i-l2+1
如果有两个以上元素,那么最后一个元素的起点就可以是2~i-l2+1
那么我们设这个起点是k
于是上一个元素的终点就可以是1~k-1
所以如果起点是k,总方案数就是∑(i=1~k-1)dp[i]
那这个东西就可以用一个前缀和s来维护
而由于终点可以是2~i-l2+1,所以一共的总方案数就是:
∑(i=2-i-l2+1)s[i-1]
也就是:
∑(i=1-i-l2)s[i]
发现这也是一个前缀和的形式,于是我们把s维护成一个前缀和ss
结合以上两个分析,得到转移为:
dp[i]=i-l2+1+ss[i-l2]
边递推边维护即可。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define seed 13131
#define ull unsigned long long
#define mode 1000000007
#define ll long long
using namespace std;
ll dp[100005];
ll s1[100005];
ll s2[100005];
char s[100005];
char t[100005];
ull has,has1[100005];
ull v;
bool flag[100005];
int main()
{
scanf("%s%s",s+1,t+1);
v=1;
int l1=strlen(s+1),l2=strlen(t+1);
for(int i=1;i<=l1;i++)
{
has1[i]=has1[i-1]*seed+s[i]-'a'+1;
}
v=1;
for(int i=1;i<=l2;i++)
{
has=has*seed+t[i]-'a'+1;
v*=seed;
}
for(int i=l2;i<=l1;i++)
{
int st=i-l2;
ull hast=has1[i]-has1[st]*v;
if(hast==has)
{
flag[i]=1;
}
}
for(int i=1;i<=l1;i++)
{
if(!flag[i])
{
dp[i]=dp[i-1];
}else
{
dp[i]=((i-l2+1)+s2[i-l2])%mode;
}
s1[i]=(s1[i-1]+dp[i])%mode;
s2[i]=(s2[i-1]+s1[i])%mode;
}
printf("%lld\n",s1[l1]);
return 0;
}
CF 494B 【Obsessive String】的更多相关文章
- 【system.string】使用说明
对象:system.string 说明:提供一系列针对字符串类型的操作 目录: 方法 返回 说明 system.string.isBlank( string ) [True | False] 检测参 ...
- 【实用类String】String类方法的应用案例:查找判断指定字符出现的次数和位置
一.应用要求 输入一个字符串,再输入要查找的字符,判断该字符在该字符串中出现的次数. 二.实现思路 1.使用substring()方法将字符串的每个字符存入数组 2.比较数组每个字符是否与指定的字符相 ...
- 【Scramble String】cpp
题目: Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty subs ...
- 【Interleaving String】cpp
题目: Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given: ...
- 题解 CF1385D 【a-Good String】
题意 定义:字符串s 为一个c-好串(c 为一个字符)时,必须满足: 当\(|s| = 1\) ,\(s = c\) 当\(|s| > 1\), \(s\) 的左半部分为全为 \(c\),右半部 ...
- 题解 CF1354B 【Ternary String】
题意 给出一个字符串,只包含 \({1,2}\) 或 \({3}\) .从中找出一个长度最短的子串,要求至少包含 \({1,2,3}\) 各一次,并输出其长度. 输入格式 本题有多组测试数据 第一行一 ...
- 【wx:for】小程序列表渲染的使用说明
wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件. 默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item,即: {{index}} . {{it ...
- 【废弃中】JavaScript 式与运算符
创建: 2017/09/25 更新: 2019/01/14 修改标题 [JavaScript 式与运算符] -> [JavaScript 式与主要Object的方法] 更新: 2019/02/ ...
- 【动态规划】【最短路】Codeforces 710E Generate a String
题目链接: http://codeforces.com/problemset/problem/710/E 题目大意: 问写N个字符的最小花费,写一个字符或者删除一个字符花费A,将当前的字符数量翻倍花费 ...
随机推荐
- P1494 [国家集训队]小Z的袜子(莫队)
题目链接:https://www.luogu.org/problemnew/show/P1494 题目大意:中文题目 具体思路:计算概率的时候,每一次是区间的移动,每一次移动,记得先将原来的记录的影响 ...
- #6284. 数列分块入门 8(区间询问等于一个数 cc 的元素,并将这个区间的所有元素改为 c)
题目链接:https://loj.ac/problem/6284 题目大意:中文题目 具体思路:还是和sqrt那个题的思路相同的,标记每一块的值是不是相同的,注意lazy下标的下放. AC代码: #i ...
- markdown自动生成侧边栏TOC /目录
http://blog.csdn.net/haleypku/article/details/51226704 此文可以只了解一下概念: http://i5ting.github.io/i5ting_z ...
- telegram即时通信软件和outline ---- by 余弦 by倾旋
第一次遇到它 是在余弦的圈子里发现的tele推送,他当时关键部分说的极其少,就三个字,你懂的..看完以后,我想哭.我真的不懂.. 我是如何突破这个术语的 近期,随着信息源的增多.(收集了大量的可靠公众 ...
- NMON使用以及nmon_analyse生成分析报表
在我们监控我们的操作系统的时候如果可以把各个硬件的监控信息生成形象化的分析报表图对于我们来说是件太好的事情了,而通过ibm的nom和nmon_analyser两者的结合完全可以实现我们的要求.首先对n ...
- Windows PowerShell 入門(8)-関数編3
この連載では.Microsoftが提供している新しいシェル.Windows PowerShellの使い方を解説します.今回は.フィルタ.スクリプトブロック.変数のスコープについて取り上げます. はじめ ...
- a标签中href属性引起的页面不跳转问题
先简单描述问题,今天在做一个简单的提交页面的时候,碰到了跳转不了的问题.其中a标签的形式<a href="" onclick="submit()"> ...
- Unity3D动态生成多边形
来自https://blog.csdn.net/qq_14903317/article/details/69668521 自由绘制多边形 https://blog.csdn.net/lei_710 ...
- UVALive 8519 Arrangement for Contests 2017西安区域赛H 贪心+线段树优化
题意 等价于给一个数列,每次对一个长度为$K$的连续区间减一 为最多操作多少次 题解: 看样例猜的贪心,10分钟敲了个线段树就交了... 从1开始,找$[i,i+K]$区间的最小值,然后区间减去最小值 ...
- [1]字符串按中文符占3位进行指定长度剪切[2]Double类型截取指定长度(指定长度=整数位+小数位)
/** 将中文字符串剪切为在当前db2(编码GBK)中所占用的长度*/ public String cutStringForDb2(String src,Integer size) { int len ...