Codeforce 535 D. Tavas and Malekas 解析(字串匹配)

今天我們來看看CF535D
題目連結

題目
給你一個字串$p$和一些$index$代表字串$p$在哪些位置會和長度為$n$的字串$s$匹配,求有多少種$s$的可能性。

前言

我還是只會$hash$

想法

$p$沒有覆蓋到的$index$數量記做$cnt$,如果那些會重疊的$p$沒有矛盾的話,那答案就是$26^$,因為有$cnt$的格子都是完全自由的。
這題有三種作法,都是要判斷重疊的$p$有沒有矛盾。注意,我們每次判斷一個從$y[i]$開始的$p$字串有沒有和前面重疊時,只需要和從$y[i-1]$開始的$p$字串比較就好,畢竟如果$y[i-2]$開始的$p$字串和$y[i-1]$開始的$p$字串沒有矛盾的話,那麼$y[i-2]$開始的$p$字串和$y[i]$開始的$p$字串就不會有矛盾(如果$y[i-1]$開始的字串和$y[i]$開始的字串沒有矛盾)。
三種匹配字串的方式是:

  1. Rolling hash,直接比對子字串的hash值看看一不一樣。
  2. KMP,只需要維護失敗函數,由於失敗函數代表一個最長的前綴的長度使得在$j-1$結束的字串的後綴和前綴一樣,那麼我們只要看看$p$字串的重疊部分是否沒有矛盾就好。
  3. Z-Algorithm,和KMP如出一轍,只不過這次$Z$函數代表從$j$開始往後的字串和整個字串的最長前綴長度。一樣只要看看$p$字串的重疊部分是否沒有矛盾就好。

程式碼(Rolling hash):

const int _n=1e6+10;
int t,n,m;
const int _N = _n; // str len
const int _p1 = 31, _M = 1000000009;
int pnM[_N] = {0}; // p^n mod M
int hp[_N] = {0}; // hash prefix
char p[_N];
int lenp,y[_n]; inline void genpnM() {
int res = 1; //p^0%M
pnM[0] = 1;
for (int i = 1; i < _N; i++) pnM[i] = res = (res * 1ll * _p1) % _M;
}
inline void genhp() { //hp[n]=hash prefix[0,n)
int res = 0;
hp[0] = 0; //[0,0) is empty string
for (int i = 1; i <= lenp; i++) hp[i] = res = (res * 1ll * _p1 + p[i - 1] * 1ll) % _M;
}
inline int dhash(char s[]) { //direct hash
int len = strlen(s);
int res = 0;
for (int i = 1; i <= len; i++) res = (res * 1ll * _p1 + s[i - 1] * 1ll) % _M;
return res;
}
inline int hashlr(int l, int r) { //[l,r)
int tmp = hp[r] * 1ll - pnM[r - l] * 1ll * hp[l] % _M;
if (tmp < 0) tmp += _M;
return tmp;
}
//以上是rolling hash模板
main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m>>p;lenp=strlen(p);rep(i,0,m){cin>>y[i];y[i]--;}
genpnM();genhp();
int cnt=y[0];rep(i,1,m){
if(y[i-1]+lenp-1>=y[i]){
if(hashlr(y[i]-y[i-1],lenp)!=hashlr(0,lenp-(y[i]-y[i-1]))){
cout<<0<<'\n';return 0;
}
}
else cnt+=y[i]-(y[i-1]+lenp-1)-1;
}cnt+=n-(y[m-1]+lenp);
if(m==0)cnt=n;
cout<<powmod(26,cnt)<<'\n';
return 0;
}

標頭、模板請點Submission看
Submission

程式碼(KMP):

const int _n=1e6+10;
int t,n,m;
char p[_n];
int lenp,y[_n],jj,F[_n];
bool vis[_n];
main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m>>p;lenp=strlen(p);rep(i,0,m){cin>>y[i];y[i]--;}
/*F[0]=-1,jj=-1;rep(i,0,lenp){
jj=F[i];
while(jj!=-1 and p[i]!=p[jj])jj=F[jj];
F[i+1]=jj+1; //if jj==-1, F[i]=0
}*/ //也行
F[0]=-1;
for(int i = 0, j = -1; i < lenp; F[++i] = ++j) { //計算失敗函數,一般來說i<lenp-1,但是這題我們需要i<lenp
while (j != -1 && p[i] != p[j]) j = F[j];
}
jj=F[lenp];
while(jj!=-1){ //看看哪些前綴可以和整條字串p的後綴匹配
vis[jj]=1;
jj=F[jj];
}
int cnt=y[0];rep(i,1,m){
if(y[i-1]+lenp-1>=y[i]){
if(!vis[lenp-(y[i]-y[i-1])]){
cout<<0<<'\n';return 0;
}
}
else cnt+=y[i]-(y[i-1]+lenp-1)-1;
}cnt+=n-(y[m-1]+lenp);
if(m==0)cnt=n;
cout<<powmod(26,cnt)<<'\n';
return 0;
}

標頭、模板請點Submission看
Submission

程式碼(Z-Algorithm):

const int _n=1e6+10;
int t,n,m,lenp,Z[_n],y[_n];
char p[_n];
main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m>>p;lenp=strlen(p);rep(i,0,m){cin>>y[i];y[i]--;}
int L = 0, R = 0;
for (int i = 1; i < lenp; i++) {
if (i > R) {
L = R = i;
while (R < n && p[R-L] == p[R]) R++;
Z[i] = R-L; R--;
} else {
int k = i-L;
if (Z[k] < R-i+1) Z[i] = Z[k];
else {
L = i;
while (R < n && p[R-L] == p[R]) R++;
Z[i] = R-L; R--;
}
}
}
int cnt=y[0];rep(i,1,m){
if(y[i-1]+lenp-1>=y[i]){
if(Z[y[i]-y[i-1]]!=lenp-(y[i]-y[i-1])){
cout<<0<<'\n';return 0;
}
}
else cnt+=y[i]-(y[i-1]+lenp-1)-1;
}cnt+=n-(y[m-1]+lenp);
if(m==0)cnt=n;
cout<<powmod(26,cnt)<<'\n';
return 0;
}

標頭、模板請點Submission看
Submission

D. Tavas and Malekas 解析(字串匹配)的更多相关文章

  1. Codeforces 535D - Tavas and Malekas

    535D - Tavas and Malekas 题目大意:给你一个模板串,给你一个 s 串的长度,告诉你 s 串中有 m 个模板串并告诉你,他们的其实位置, 问你这样的 s 串总数的多少,答案对1e ...

  2. Codeforces Round #299 (Div. 2) D. Tavas and Malekas kmp

    题目链接: http://codeforces.com/problemset/problem/535/D D. Tavas and Malekas time limit per test2 secon ...

  3. JVM-class文件完全解析-字段表集合

     字段表集合 这个class文件的解析,分析得有点太久了.前面介绍类魔数,次版本号,主板本号,常量池入口,常量池,访问标志,类索引,父类索引和接口索引集合.下面就应该到字段表集合了.  紧接着接口索引 ...

  4. Tavas and Malekas

    题面 题目描述 给你两个字符串a和b,告诉所有你b在a中一定匹配的位置,求有中不同的字符串a.a的长度为n,b的长度为m,一定匹配的位置有p个.若b在a中的一定匹配的位置为x,说明a[x-x+m-1] ...

  5. codeforces 535D. Tavas and Malekas KMP

    题目链接 又复习了一遍kmp....之前都忘光了 #include<bits/stdc++.h> using namespace std; #define pb(x) push_back( ...

  6. CF #299 div1 B. Tavas and Malekas KMP-next数组

    题目链接:http://codeforces.com/contest/536/problem/B 一个原始字符串,一个未知字符串,每一次从pos[i]开始覆盖未知字符串,问最后字符串的形式,以及判断过 ...

  7. Codeforces Round #299 (Div. 2)D. Tavas and Malekas

    KMP,先预处理按每个节点标记,扫一遍更新每个匹配位置,最后kmp判断是否有重合而且不相同的地方 注意处理细节,很容易runtime error #include<map> #includ ...

  8. D. Tavas and Malekas DFS模拟 + kmp + hash || kmp + hash

    http://codeforces.com/contest/535/problem/D 如果真的要把m个串覆盖上一个串上面,是可以得,不会超时. 要注意到一点,全部覆盖后再判断时候合法,和边放边判断, ...

  9. 【Codeforces Round #299 (Div. 2) D】Tavas and Malekas

    [链接] 我是链接,点我呀:) [题意] 给你n个位置,然后让你从某些位置开始的|p|个位置,填上p这个字符串. 问你填的时候是否会发生冲突->输出0 否则输出最终n个位置组成的可能的字符串的总 ...

随机推荐

  1. 二分类问题续 - 【老鱼学tensorflow2】

    前面我们针对电影评论编写了二分类问题的解决方案. 这里对前面的这个方案进行一些改进. 分批训练 model.fit(x_train, y_train, epochs=20, batch_size=51 ...

  2. PyCharm2018.3.5下载和安装及永久破解详解(成功案例)

    靓仔靓女,你是否在网上找了很多的方法都破解不了PyCharm,是有原因的!无论什么编程工具都不要下载近一到/两年内的版本,人家即把网上的一些破解方法修复了,而且还在测试阶段,不稳定就完事了我装的是20 ...

  3. 牛客在线习题:链表的k各节点翻转

    题目描述 将给出的链表中的节点每\ k k 个一组翻转,返回翻转后的链表如果链表中的节点数不是\ k k 的倍数,将最后剩下的节点保持原样你不能更改节点中的值,只能更改节点本身.要求空间复杂度 \ O ...

  4. 2020.09 问题总结(Oracle-->MySQL、Maven、JSP-->Thymeleaf、Druid)

    2020.09 问题总结(Oracle-->MySQL.Maven.JSP-->Thymeleaf.Druid) 数据库建表 Oracle 转 MySQL 问题 Oracle MySQL ...

  5. 《To B产品经理进阶》

    一.沙漏哟:To B产品技术标准化(全网独家) 经济机器是怎样运行的(超级简单模式理解经济运行规律) <俞军产品方法论>(思维模型.交易模型.经济学.心理学) <深度思考六步法> ...

  6. git的项目完整操作

    今天来说下项目中git 的使用,针对常规操作: 然后执行  git status  可以看到目前的状态: 再执行添加操作      git add . 添加所有文件 接着执行提交命令  git com ...

  7. FreeType2使用总结(转)

    一.FreeType2简介 1. 是一个免费.开源.可移植且高质量的字体引擎: 2. 支持多种字体格式文件,并提供了统一的访问接口: 3. 支持单色位图.反走样位图渲染,这使字体显示质量达到Mac的水 ...

  8. linux块设备驱动---概念与框架(转)

    基本概念   块设备(blockdevice) --- 是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性 ...

  9. 通过MapReduce降低服务响应时间

    在微服务中开发中,api网关扮演对外提供restful api的角色,而api的数据往往会依赖其他服务,复杂的api更是会依赖多个甚至数十个服务.虽然单个被依赖服务的耗时一般都比较低,但如果多个服务串 ...

  10. Redis不重启的情况下 切换持久化模式

    确保redis版本在2.2以上 [root@localhost /]# redis-server -v Redis server v=4.0.10 sha=00000000:0 malloc=jema ...