字符串匹配--(K)MP模板
大白书型模板,并没有写成函数形式:
关于p数组(失配指针数组)的含义: - 数组下标从0开始
p[i]表示当发现待匹配串(s)已匹配位置与模板串(t)的t[i]不匹配时,t中最近一个可以尝试继续匹配的位置。即当已经完成了s串与t[0]~t[i-1]的匹配时,发现s串后一个字符与t[i]不匹配,此时s串到当前不构成匹配的位置前可以视为与 t[0] ~ t[ p[i]-1 ] 完成了匹配,因此可以继续匹配s串当前字符与 t[ p[i] ] 。此时如果仍然不匹配可以继续对 t 当前不匹配的位置做失配转跳,直至转跳到t中的当前匹配位置为0位置。
因此实际上p[i]也具有这样的性质:t[0]~t[ p[i]-1 ] 是 t[0]~t[i-1] 的所有前缀中的最长可匹配后缀。
此外,对于一个长度为 m 的串自匹配,在此模板中 m-p[m] 就是这个串的最小循环节长度(最后一个循环可以不完整) - 数组下标从0开始
另一个关于自匹配后的失配指针的性质:对于该串的所有可以作为循环节的长度是:m-p[m] , m-p[p[m]] , m-p[p[p[m]]]……直到 p[x] = 0。 - 数组下标从0开始
这个是下标从0开始的:
#include <stdio.h>
#include <string.h>
typedef long long ll;
#define MP make_pair
#define PB push_back
const int mod = 1e9 + ;
const double eps = 1e-;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6 + ;
const int maxm = 1e5 + ; char s[maxn],t[maxm]; //s为待匹配串,t为模板串
int p[maxn]; //自匹配数组 int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%s%s", t, s); //这个是字符串从下标0开始的
int i,j = ,ans=; // j = 0 注意, ans记录字符串出现次数
int n = strlen(s), m = strlen(t); //在题目中遇到过,其实strlen很慢,所以如果不先存起来可能有TLE的风险
p[] = p[] = ; //初始化自匹配数组
for(i = ; i < m ; ++ i){ //自匹配
while(j && t[i] != t[j])j = p[j];
if(t[i] == t[j])++ j;
p[i+] = j;
}
j = ; //注意 j=0
for(i = ; i < n ; ++ i){ //串匹配
while(j && s[i] != t[j])j = p[j];
if(s[i] == t[j])++ j;
if(j == m){
ans++; //此处记录出现次数(模板串在待匹配串中可重叠),或改为直接break表示是否出现过
}
}
printf("%d\n",ans);
}
return ;
}
数组下标从1开始:
#include<stdio.h>
#include<string.h> const int maxn=1e6+;
const int maxm=1e4+; char s[maxn],t[maxm];
int p[maxm]; int main(){
while(scanf("%s%s",s+,t+)!=EOF){ // 。。这个是从下标1开始的,恩修改的还是比较多的所以不是很建议
int i,j,ans=;
int n=strlen(s+),m=strlen(t+);
p[]=p[]=;
for(i=;i<=m;i++){
j=p[i];
while(j>&&t[i]!=t[j])j=p[j];
p[i+]=t[i]==t[j]?j+:;
}
j=;
for(i=;i<=n;i++){
while(j>&&s[i]!=t[j])j=p[j];
if(s[i]==t[j])j++;
if(j==m+){
ans++;
}
}
printf("%d\n",ans);
}
return ;
}
字符串匹配--(K)MP模板的更多相关文章
- 【Luogu P3375】字符串匹配KMP算法模板
Luogu P3375 模式串:即题目中的S2所代表的意义 文本串:即题目中的S1所代表的意义 对于字符串匹配,有一种很显然的朴素算法:在S1中枚举起点一位一位匹配,失配之后起点往后移动一位,从头开始 ...
- 字符串匹配--扩展KMP模板
对于一个字符串 s 以及子串 t ,扩展KMP可以用来求 t 与 s 的每个子串的最长公共前缀 ext [ i ],当然,如果有某个 ext 值等于 t 串的长度 lent ,那么就说明从其对应的 i ...
- 字符串匹配--manacher算法模板
manacher算法主要是处理字符串中关于回文串的问题的,它可以在 O(n) 的时间处理出以字符串中每一个字符为中心的回文串半径,由于将原字符串处理成两倍长度的新串,在每两个字符之间加入一个特定的特殊 ...
- 字符串匹配--AC自动机模板
AC自动机果断是神一样的东西,我赶在比赛前学习还是有用的,AC自动机最基本的是可以解决多个模式串在一个长字符串中出现的种类数或次数: 我暂时还是修改大神们的模板的昂 满满个人注释版帮助自己理解版: / ...
- P3375 【模板】KMP字符串匹配 (KMP模板)
题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如果你不知道这是什么意思也不要问,去百度 ...
- P3375 模板 KMP字符串匹配
P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long lo ...
- 字符串KMP——用途广泛的字符串匹配算法 + 扩展KMP——特殊定义的字符串匹配
引 入 引入 引入 " SY 和 WYX 在看毛片.(几 毛 钱买到的动作 片,毛 片) WYX 突然想回味一个片段,但是只记得台词里面有一句挺长的 " ∗ ∗ ∗ ∗ **** ...
- 洛谷—— P3375 【模板】KMP字符串匹配
P3375 [模板]KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如 ...
- KMP字符串匹配 模板 洛谷 P3375
KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...
- 洛谷P3375 - 【模板】KMP字符串匹配
原题链接 Description 模板题啦~ Code //[模板]KMP字符串匹配 #include <cstdio> #include <cstring> int cons ...
随机推荐
- (GoRails) 自动侦测用户的时区,使用javascript 的jszt库。
传统方法见:http://www.cnblogs.com/chentianwei/p/9369904.html ⚠️: 两个方法最后都要有controller中的类似before_action :se ...
- Rspec: everyday-rspec实操: 第8章DRY. (6个方法,其中3个方法好上手)
Don't Repeat Yourself. • 把操作步骤提取到辅助模块中;✅ • 通过let复用测试中的实例变量;✅ • 把通用的设置移到共享的情景中;⚠️(不喜欢) • 在RSpec和rspec ...
- oracle使用(1)
纯粹是记录工作中使用的分析函数或是语法点,不做其他用处. (1) with as 先举个例子吧: 有两张表,分别为A.B,求得一个字段的值先在表A中寻找,如果A表中存在数据,则输出A表的值:如果A表中 ...
- hdoj4283 You Are the One
题意:每个人出场时获得等待时间*值的unhappy值.有个栈换出场顺序.问怎样最小? 一开始的时候觉得在中间取断点,dp[i][j]表示区间全出场后的最小值.那么dp[i][j]=dp[i][k]+d ...
- Anton and School - 2 CodeForces - 785D (组合计数,括号匹配)
大意: 给定括号字符串, 求多少个子序列是RSGS. RSGS定义如下: It is not empty (that is n ≠ 0). The length of the sequence is ...
- IDEA搭建ssm框架测试衍生出的问题The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: D:\Develop\jdk7\jdk1.7.0_79\bin;
最近玩起IDEA这开发工具,搭建ssm框架测试时,部署项目出现如下问题: 信息: The APR based Apache Tomcat Native library which allows opt ...
- c++中的引用详解
什么是引用? 引用是C++语言的一个特殊的数据类型描述,用于在程序的不同的部分使用两个以上的变量名指向同一块地址,使得对其中任何一个变量的操作实际上都是对同一地址单元进行的. 使用时的注意事项: 引用 ...
- HDU-2829 Lawrence (DP+四边形不等式优化)
题目大意:有n个敌方军火库呈直线排列,每个军火库有一个值vi,并且任意相邻的两个库之间都有通道相连.对于任意一条连起来的军火库链,它对我方的威胁可以用函数w(i,j)表示为:w(i,j)=vi*sum ...
- C#XML注释
注释 <c> 将说明中的文本标记为代码 <code> 提供了一种将多行指示为 ...
- HDU 3720 深搜 枚举
DES:从23个队员中选出4—4—2—1共4种11人来组成比赛队伍.给出每个人对每个职位的能力值.给出m组人在一起时会产生的附加效果.问你整场比赛人员的能力和最高是多少. 用深搜暴力枚举每种类型的人选 ...