[CF494B] Obsessive String
Hamed has recently found a string t and suddenly became quite fond of it. He spent several days trying to find all occurrences of t in other strings he had. Finally he became tired and started thinking about the following problem. Given a string s how many ways are there to extract k ≥ 1 non-overlapping substrings from it such that each of them contains string t as a substring? More formally, you need to calculate the number of ways to choose two sequences a1, a2, ..., ak and b1, b2, ..., bk satisfying the following requirements:
- k ≥ 1



t is a substring of string saisai + 1... sbi (string s is considered as 1-indexed).
As the number of ways can be rather large print it modulo 109 + 7.
Input consists of two lines containing strings s and t (1 ≤ |s|, |t| ≤ 105). Each string consists of lowercase Latin letters.
Print the answer in a single line.
此题两种DP方式。
先预处理出来b串在a串中匹配的位置,然后开始DP。
设$f[i]$表示考虑到$i$位置,且$i$的最后一个字符串与b串是匹配的方案数。
显然如果$i$不是b的匹配位置,$f[i]=f[i-1]$。
如果$i$是b的匹配位置,首先考虑只有一个串, 那么答案就是$i-lb+1$,因为$1$到$i-lb+1$的所有位置都可以作为一个开始。
那如果是多个串呢?如果我们设最后一个串从位置$k$开始,那么前面的所有的方案数就是$\large \sum_{i=1}^{k}f[i]$,对于每个位置k求和,就是$\large \sum_{k=1}^{i-lb} \sum_{j=1}^{k} f[j]$。
这样只用记录一下f的前缀和和f的前缀和的前缀和就可以快速转移啦。
代码在后面贴。
还有一种方法,状态的定义略微的有些不同,设$f[i]$表示,到第i个位置之前总共有多少方案,其实就是前缀和了一下。
每次记录上一个匹配点,从上一个匹配点开始转移。
代码贴后面了。
找匹配点可以用kmp,或者hash都行。
方法1:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
#define reg register
#define mod 1000000007
int la, lb;
char a[], b[];
unsigned long long hsha[], hshb[], fac[];
bool End[];
int f[], sum[], Ssum[];
int ans; int main()
{
scanf("%s%s", a + , b + );
la = strlen(a + ), lb = strlen(b + );
for (reg int i = ; i <= la ; i ++) hsha[i] = hsha[i - ] * + (a[i] - 'a' + );
for (reg int i = ; i <= lb ; i ++) hshb[i] = hshb[i - ] * + (b[i] - 'a' + );
fac[] = ;
for (reg int i = ; i <= max(la, lb) ; i ++) fac[i] = fac[i - ] * ;
for (reg int i = lb ; i <= la ; i ++)
if (hsha[i] - hsha[i - lb] * fac[lb] == hshb[lb]) End[i] = ;
for (reg int i = ; i <= la ; i ++)
{
if (!End[i]) f[i] = f[i-];
else f[i] = Ssum[i - lb] + i - lb + ;
sum[i] = sum[i-] + f[i];if(sum[i] >= mod) sum[i] -= mod;
Ssum[i] = Ssum[i-] + sum[i];if(Ssum[i] >= mod) Ssum[i] -= mod;
}
for (reg int i = ; i <= la ; i ++)
ans = (ans + f[i]) % mod;
cout << ans << endl;
return ;
}
方法2:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
#define reg register
#define mod 1000000007
int la, lb;
char a[], b[];
int nxt[];
bool End[];
int f[], sum[]; int main()
{
scanf("%s%s", a + , b + );
la = strlen(a + ), lb = strlen(b + );
int k = ;
for (reg int i = ; i <= lb ; i ++)
{
while(k and b[i] != b[k + ]) k = nxt[k];
if (b[k + ] == b[i]) k ++;
nxt[i] = k;
}
k = ;
for (reg int i = ; i <= la ; i ++)
{
while(k and a[i] != b[k + ]) k = nxt[k];
if (b[k + ] == a[i]) k ++;
if (k == lb) End[i] = ;
}
int lst = -;
for (reg int i = ; i <= la ; i ++)
{
f[i] += f[i-];
if (End[i]) lst = i - lb + ;
if (lst != -) f[i] += sum[lst - ] + lst;
if (f[i] >= mod) f[i] -= mod;
sum[i] = sum[i-] + f[i];
if (sum[i] >= mod) sum[i] -= mod;
}
cout << f[la] << endl;
return ;
}
[CF494B] Obsessive String的更多相关文章
- [Codeforces-div.1 494B]Obsessive String
[CF-div.1 B]Obsessive String 题目大意 两个字符串\(S,T\),求划分方案数使得一个集合中两两划分不相交且划分都包含字符串\(T\) 试题分析 kmp先求出那个位置匹配. ...
- [codeforces494B]Obsessive String
[codeforces494B]Obsessive String 试题描述 Hamed has recently found a string t and suddenly became quite ...
- Codeforces Round #282 (Div. 1)B. Obsessive String KMP+DP
B. Obsessive String Hamed has recently found a string t and suddenly became quite fond of it. He s ...
- CodeForces 494B Obsessive String ——(字符串DP+KMP)
这题的题意就很晦涩.题意是:问有多少种方法,把字符串s划分成不重叠的子串(可以不使用完s的所有字符,但是这些子串必须不重叠),使得t串是所有这些新串的子串.譬如第一个样例,"ababa&qu ...
- Codeforces Round #282 Div.1 B Obsessive String --DP
题意: 给两个串S,T,问能找出多少的S的(a1,b1)(a2,b2)..(ak,bk),使Sa1---Sb1,...Sak---Sbk都包含子串T,其中k>=1,且(a1,b1)...(ak, ...
- Codeforces 494B Obsessive String
http://www.codeforces.com/problemset/problem/494/B 题意:给出两个串S,T,求有几种将S分成若干个子串,满足T都是这若干个子串的子串. 思路:f[n] ...
- CF 494B 【Obsessive String】
很有趣的一道题 这道题提议很难懂,其实就是让你求合法的集合数目.合法的集合定义为: 1.集合中的所有串都是s的子串,且互不重叠 2.集合中的所有串都含有子串t. 看到网上很多题解说要用kmp,但我就不 ...
- 【codeforces #282(div 1)】AB题解
A. Treasure time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...
- DP × KMP
几道用到KMP的DP题: hdu 5763 hdu 3689 hdu 3336 codeforces 494B codevs 3945 关于KMP的nx数组: 如果在本文中看见 ...
随机推荐
- 【学习笔记】第二章 python安全编程基础---python爬虫基础(urllib)
一.爬虫基础 1.爬虫概念 网络爬虫(又称为网页蜘蛛),是一种按照一定的规则,自动地抓取万维网信息的程序或脚本.用爬虫最大的好出是批量且自动化得获取和处理信息.对于宏观或微观的情况都可以多一个侧面去了 ...
- charles 设置为chrome代理
本文参考:charles 设置为chrome代理 将charles设置为chrome的代理 需要注意的是,Chrome 和 Firefox 浏览器并不一定使用的就是本机,可能是一些代理工具,而 Cha ...
- Java开发者薪资最低?程序员只能干到30岁?国外真的没有996?Intellij真的比Eclipse受欢迎?
Stack Overflow作为全球最大的程序设计领域的问答网站,每年都会出据一份开发者调查报告.近日,Stack Overflow公布了其第9次年度开发者调查报告(https://insights. ...
- Swift从入门到精通第七篇 - 扩展 初识
扩展(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 扩展 为类.结构体.枚举.协议添加新功能,同OC的分类很像,但扩展没有名字 扩展可以添加计算实例属性和计算类型属性(不能添加 ...
- let与var的区别
1.let作用域局限于当前代码块 文章中//后面的均为打印结果 代码1: { var str1 = "小花"; let str2 = "小明"; console ...
- mysql having和using使用
1.having当用到聚合函数sum,count后,又需要筛选条件时,就可以考虑使用having,因为where是在聚合前筛选记录的,无法和统计函数一起使用,而having在聚合后筛选记录,可以和统计 ...
- ng-cli新建项目
tip:所有的命令是红色标签 , 链接为蓝色标签 使用ng-cli创建新的项目一般需要安装一些新的东西后才可以进行创建成功 1.需要先安装node.js 链接: https://nodejs.org ...
- spring5 源码深度解析----- AOP代理的生成
在获取了所有对应bean的增强后,便可以进行代理的创建了.回到AbstractAutoProxyCreator的wrapIfNecessary方法中,如下所示: protected static fi ...
- [scrapy-redis] 将scrapy爬虫改造成分布式爬虫 (2)
1. 修改redis设置 redis默认处在protection mode, 修改/etc/redis.conf, protected-mode no, 或者给redis设置密码, 将bind 127 ...
- Laravel Entrust 权限管理扩展包的使用笔记
简介 Entrust 是一个简洁而灵活的基于角色进行权限管理的 Laravel 扩展包.针对 Laravel 5,官方推荐的安装版本是 5.2.x-dev.它的详细使用方法请查看 Entrust Gi ...