一、学习记录
犹记当年学习C语言的字符串的时候那个悲情。。。
于是组队之后果断声明:鶸不玩字符串
然后将字符串丢给队友。。。
后来觉得吧,一些基础的东西还是要会的,比如KMP
粗浅的学了下KMP算法,也不敢瞎说什么,主要整理了下模板
学习记录:
主要看了刘大大的蓝书《算法竞赛入门经典--训练指南》
还有几篇博客:
1. KMP算法详解
2.KMP算法详解
二、两种模板
初期使用的模板:
#define mem(a,x) memset(a,x,sizeof(a))
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000;
/*
KMP 算法模板
时间复杂度 : O(n+m) [其中 n,m 是两字符串的长度]
说明:
1. a是长串 s是短串 即 a.size >= s.size
2.实现了“查找第一次匹配的位置” “匹配的次数” “记录所有匹配区间”三个功能
3.三个功能的实现代码非常相似,第3个功能可以同时实现前2个的功能
*/
struct KMP
{
int f[N + 7];
void getfill (string s) //预处理
{
memset (f, 0, sizeof (f) ); //根据其前一个字母得到
for (int i = 1; i < s.size(); i++)
{
int j = f[i];
while (j && s[i] != s[j])
j = f[j];
f[i + 1] = (s[i] == s[j]) ? j + 1 : 0;
}
}
int finds (string a, string s) //找到第一次匹配的位置 a.size >= s.size
{
getfill (s);
int j = 0;
for (int i = 0; i < a.size(); i++)
{
while (j && a[i] != s[j]) j = f[j];
if (a[i] == s[j]) j++;
if (j == s.size() )
{
return i - s.size() + 1; //返回小串在大串中第一次出现的位置
}
}
return -1;//不匹配返回-1
}
int findtimes(string a,string s)//返回匹配次数
{
getfill(s);
int j = 0;int times = 0;
for (int i = 0;i < a.size();++i)
{
while (j&&a[i] != s[j]) j = f[j];
if (a[i] ==s[j]) j++;
if (j == s.size())
{
times++;
}
}
return times;//不匹配的times将是0
}