目录

总结

Number Sequence

Oulipo

剪花布条

Cyclic Nacklace

Period

Power Strings

Seek the Name, Seek the Fame

Blue Jeans

Simpsons’ Hidden Talents

Count the string


总结

题单链接传送门

kmp算法,最核心的就是理解pmt数组,pmt数组前缀后缀相等的最大长度,那么可以理解为记录为上次匹配的位置,所以每次递归的长度是j-pmt[j-1];其次就是pmt可以判断是否有循环节(n%(n−pmt[n-1])==0 && pmt[n-1]),这里的n-pmt[n-1]是最小的循环节,那么循环次数就是n/(n-pmt[n-1]).

Number Sequence

原题链接传送门

kmp模板题,要注意的是这里是数字,不能让它们转化为字符串再去求(这里没仔细读题wa了很多发),直接按数组去求就好了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#define int long long
using namespace std;const int N = 1e6 + 9;
int n, m;
int pmt[N];
int s[N], p[N];signed main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int t;std::cin >> t;while (t--){int n, m;cin >> n >> m;for (int i = 0; i < n; i++) cin >> s[i];for (int j = 0; j < m; j++) cin >> p[j];for (int i = 1, j = 0; i < m; i++){while (j && p[i] != p[j]) j = pmt[j - 1];if (p[i] == p[j]) j++;pmt[i] = j;}bool flag = 0;for (int i = 0, j = 0; i < n; i++){while (j && s[i] != p[j]) j = pmt[j - 1];if (s[i] == p[j]) j++;if (j == m){flag = true;cout << i - j + 2 << "\n";break;}}if(!flag) cout << -1 << "\n";}return 0;
}

Oulipo

原题链接传送门

模式串在匹配串中出现的次数,模板题。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#define int long long
using namespace std;const int N = 1e6 + 9;
int pmt[N];void get_pmt(const string& p) {for(int i = 1, j = 0; i < p.size(); i++){while(j && p[i] != p[j]) j = pmt[j - 1];if(p[i] == p[j]) j ++;pmt[i] = j;}
}int kmp(const string& s, const string& p) {int ans = 0;for(int i = 0, j = 0; i < s.size(); i++){while(j && s[i] != p[j]) j = pmt[j - 1];if(s[i] == p[j]) j ++;if(j == p.size()){ans++;j = pmt[j - 1];}}return ans;
}signed main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int t;std::cin >> t;while(t--){  string p, s;cin >> p >> s;get_pmt(p);cout << kmp(s, p) << endl;}return 0;
}

剪花布条

原题链接传送门

一个字符串能分成相同的几段,这里要注意由于不能有重叠部分所以在递归匹配时重新从0开始即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>using namespace std;const int N = 1e6 + 9;
int pmt[N];void get_pmt(const string& s) { for(int i = 1, j = 0; i < s.size(); i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}
}int kmp(const string& s, const string& p) {int ans = 0;for(int i = 0, j = 0; i < s.size(); i++){while(j && s[i] != p[j]) j = pmt[j - 1];if(s[i] == p[j]) j ++;if(j == p.size()){ans++;// j = pmt[j - 1];j = 0;}}return ans;
}int main()
{ios::sync_with_stdio(false);cin.tie(0);string s, p;while(cin >> s){if(s == "#") break;cin >> p;get_pmt(s);int m = p.size();cout << kmp(s, p) << endl;}return 0;
}

Cyclic Nacklace

原题链接传送门

题意:一个字符串最少加多少个字符能使字符串变成周期循环.

思路:最小循环节为n-pmt[n-1],所以加的最小长度就是n-pmt[n-1]-pmt[n-1]%(n-pmt[n-1]).

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 9;
int n, m;
int pmt[N];
char s[N];signed main()
{int t;scanf("%d",&t);while(t--) {scanf("%s",s);int n = strlen(s);for(int i = 1, j = 0; i < n; i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}int l = pmt[n - 1], r = n - l;if(l && l % r == 0) cout << 0 << endl;else cout << r - l % r << endl;}return 0;
}

Period

原题链接传送门

一个字符串,问在所有的[0, i]区间是否有完整的循环节,同样利用了pmt对循环节的求解。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;const int N = 1e6 + 9;
int n, m;
int pmt[N];signed main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int n;int test = 0;while(cin >> n && n != 0) {string s;cin >> s;for(int i = 1, j = 0; i < n; i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}cout << "Test case #" << ++test << "\n";for(int i = 0; i < n; i++){int j = i + 1;int k = j - pmt[i];if(j % k == 0 && pmt[i]) cout << j << " " <<  j / k << "\n";}cout << "\n";}return 0;
}

Power Strings

原题链接传送门

题意:假设s可以由t重复k次拼成,即s=tttt……tt,我们称为s=t^k,k是s的幂次。先给定一个字符串s,求最大的幂次n使得存在t满足s=t^n。先看看是不是周期循环,否输出1是输出循环次数即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;const int N = 1e6 + 9;
int pmt[N];void get_pmt(const string& s) { for(int i = 1, j = 0; i < s.size(); i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}
}int main()
{ios::sync_with_stdio(false);cin.tie(0);string s;while(cin >> s){if(s == ".") break;get_pmt(s);int n = s.size();int m = n - 1;if(n % (n - pmt[m])) std::cout << "1\n";else std::cout << n / (n - pmt[m]) << "\n";}return 0;
}

Seek the Name, Seek the Fame

原题链接传送门

题意:在每个字符串中求出所有既是前缀又是后缀的子串长度。

思路:pmt表示前缀与后缀相等的最大长度,递归pmt即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;const int N = 1e6 + 9;
int n, m;
int pmt[N], ans[N];
char s[N];signed main()
{while(~scanf("%s",s)) {int n = strlen(s);for(int i = 1, j = 0; i < n; i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}int cnt = 0;for(int j = n; j; j = pmt[j - 1]) ans[++cnt] = j;for(int i = cnt; i; i--) cout << ans[i] << " \n"[i == 1];}return 0;
}

Blue Jeans

原题链接传送门

多个字符串的公共子序列,水题暴力枚举即可。

#include <iostream>
#include <vector>
#include <set>
signed main(){int T, n;std::cin >> T;while (T--){std::cin >> n;std::string s, t;std::vector<std::string> str;std::set<std::string> ans;for (int i = 0; i < n; i++)std::cin >> s, str.push_back(s);bool f, fy = 0;s = str[0];for (int i = 60; i >= 3; i--){for (int j = 0; i + j <= 60; j++){f = 1, t = s.substr(j, i);for (int k = 1; k < str.size(); k++)if ((int)str[k].find(t) == -1){f = 0;break;}if (f) ans.insert(t);}if (!ans.empty()){fy = 1;break;}}std::cout << ((fy) ? (*(ans.begin())) : "no significant commonalities");std::cout << "\n";}return 0;
}

Simpsons’ Hidden Talents

原题链接传送门

题意:两个字符串s,t,输出同时作为s前缀和t后缀的最长字符串,然后输出该字符串的长度

思路:根据题意,我们可以选择将两个字符拼在一起,最后找到长度不大于s或t的任意一个既是前缀又是后缀的字符串即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <stack>
#include <vector>
#define int long long
using namespace std;const int mod = 10007;
const int N = 1e6 + 9;
int n, m;
int pmt[N];void get_pmt(const string& s) { for(int i = 1, j = 0; i < s.size(); i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}
}signed main()
{ios::sync_with_stdio(false);cin.tie(nullptr);string s, p;while(cin >> s >> p) {int lens = s.size(), lenp = p.size();s = s + p;get_pmt(s);n = s.size();int ans = pmt[n - 1];while(ans > lens || ans > lenp) ans = pmt[ans];if(ans==0) {cout<<0<<endl;continue;}cout << s.substr(0, ans) << " " << ans << endl;}return 0;
}

Count the string

原题链接传送门

题意:给定一个字符串s,求s的每个前缀在此字符串中出现的次数,然后对次数求和,然后再对10007取模,就是要输出的答案。

思路:主要考察对pmt数组的理解,每个前缀至少出现一次,如果i匹配失败,会回到pmt[i-1],所以当前的字符串包含pmt[i-1]包含的前缀和它本身。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <stack>
#include <vector>
#define int long long
using namespace std;const int mod = 10007;
const int N = 1e6 + 9;
int n, m;
int pmt[N];
string s;void get_pmt(const string& s) { for(int i = 1, j = 0; i < s.size(); i++){while(j && s[i] != s[j]) j = pmt[j - 1];if(s[i] == s[j]) j ++;pmt[i] = j;}
}signed main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int t;cin >> t;while(t--) {cin >> n >> s;get_pmt(s);int ans = 0;for(int i = 0; i < n; i++) if(pmt[i]) ans = (ans + 1) % mod;cout << (ans + n) % mod << "\n";}return 0;
}

2022/11/5 0:45补11.3-11.4


11.3-11.4kmp专题训练相关推荐

  1. 7的整除特征 三位一截_数的整除(能被7、9、11、13整除的数的特征)专题训练

    数的整除(能被 7 . 9 . 11 . 13 整除的数的特征)专题训练 知识梳理: 1 .整数 a 除以整数 b(b≠0) ,所得的商正好是整数而没有余数,我们就说 a 能被 b 整 可以说 b 能 ...

  2. 洛谷专题训练 ——【算法1-1】模拟与高精度

    洛谷题单[算法1-1]模拟与高精度 ACM-ICPC在线模板 题单链接: [算法1-1]模拟与高精度 下面的这一坨都是洛谷题单上的东东 题单简介 恭喜大家完成了第一部分语言入门,相信大家已经可以使用 ...

  3. 11.2 正睿停课训练 Day15

    目录 2018.11.2 正睿停课训练 Day15 A 郁闷的小G(二分) B 小G的树(树形DP) C 数的距离(思路) 考试代码 B C 2018.11.2 正睿停课训练 Day15 时间:3.5 ...

  4. C++——素数(质数)专题训练4

    作者有话说:时隔一年的质数专题训练更新啦~  近期会多多更新笔记!!! 1255:求质数 时间限制: 1.000 Sec  内存限制: 128 MB 题目描述 输入正整数n,输出不大于n的最大质数 输 ...

  5. 杭电ACM-LCY算法进阶培训班-专题训练(矩阵快速幂)

    杭电ACM-LCY算法进阶培训班-专题训练(矩阵快速幂)[模板] 传送门 杭电ACM-LCY算法进阶培训班-专题训练(矩阵快速幂)[模板] 矩阵快速幂模板 Count Problem Descript ...

  6. 二次函数回归方程_高三专题(下载)||【专题1】高三复习三角函数专题训练

    不学无数 高三复习三角函数专题训练 长按二维码识别 下载电子稿 (下载问题,下方留言) 高三复习三角函数专题训练 专题训练 不学无数 高三复习三角函数专题训练 长按二维码识别 下载电子稿 (下载问题, ...

  7. 欧姆定律的c语言编程例题,欧姆定律计算题专题训练(经典全面附答案).doc

    欧姆定律计算题专题训练(经典全面附答案) 欧姆定律计算题专题训练 1.如图所示的电路中,电压表V1的示数为9伏,电压表V2的示数为3伏,那么R1与R2的阻值之比为 A.2:1 B.1:2 C.3:1 ...

  8. 11.10/11.11/11.12 安装PHP5 11.13 安装PHP7

    2019独角兽企业重金招聘Python工程师标准>>> 11.10/11.11/11.12 安装PHP5 PHP官网www.php.net 当前主流版本为5.6/7.1 安装前请安装 ...

  9. 11.28 限定某个目录禁止解析php 11.29 限制user_agent 11.30/11.31 php相关配置

    - 11.28 限定某个目录禁止解析php - 11.29 限制user_agent - 11.30/11.31 php相关配置 - 扩展 - apache开启压缩 http://ask.apelea ...

  10. MyBatis-学习笔记11【11.Mybatis的缓存】

    Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...

最新文章

  1. Azure Arc 正式商用、Power Platform+GitHub 世纪牵手,一文看懂 Ignite 2020
  2. 云网融合 — 云网之争
  3. 【JavaSE02】Java基本语法-练习
  4. [HNOI2008]神奇的国度
  5. windows如何生成ssh密钥
  6. 美团技术:到店供应链及商品平台建设实践(胶片)
  7. Swift中文教程(十七) 可选链
  8. Linux中的sort排序
  9. 新路由3鸡血版固件_【2020.8.17】newifi3版LEDE+Padavan+openwrt19.07自编译稳定固件
  10. 大数据资料全解析(352个案例+大数据交易白皮书+国内外政策汇篇)
  11. Oracle建表规范
  12. 倾斜摄影——3维建模软件PhotoScan教程(附安装包+教学视频)
  13. matlab 循环和判断语句,matlab中循环语句与for循环
  14. Battleship
  15. coj 1256 天朝的单行道
  16. mysql面试题总结_mysql面试题小结
  17. PostgreSQL树形结构的递归查询
  18. MemFire教程|PostgreSQL RLS介绍
  19. 一个IP地址搜索服务
  20. SpringMVC程序开发

热门文章

  1. php商城系统源码的好处有哪些?
  2. 360安全卫士企业版本 跳过卸载保护密码
  3. Mysql复制原理以及流程
  4. 计算机无法识别 此硬盘,如果计算机无法识别硬盘驱动器,该怎么办?
  5. android系统与苹果手机号码,苹果手机号码怎么导入另一个手机安卓(全程图解其操作流程)...
  6. Win10下次使用debug进入DOS进行汇编开发
  7. sgu-244 Height, Bisector and Median
  8. r语言实现岭回归_R语言回归篇
  9. AtCoder Beginner Contest 224题解 A-G
  10. 自下而上合并排序算法