KMP算法:实现两个字符串的匹配。
KMP讲解
//KMP模板
#include<bits/stdc++.h>
using namespace std;
void get_next(string t, int* next){
int i=0;
int j=-1;
next[0]=-1;
while(i<t.length()){
if(j==-1||t[i]==t[j]){
i++,j++;
next[i]=j;
}
else{
j=next[j];
}
}
}
int kmp(string s, string t){
int next[t.length()+5];
get_next(t, next);
int i=0;
int j=0;
while(i<s.length()&&j<t.length()){
if(j==0||s[i]==t[j]){
i++,j++;
}
else{
j=next[j];
}
}
if(i==s.length()){
return -1;
}
if(j==t.length()){
return i-t.length()+1;
}
}
int main(){
string a, b;
a="abcde";
b="cd";
cout<<kmp(a, b);
return 0;
}
例一:子串
牛客题目链接
给出一个正整数n,我们把1…n在k进制下的表示连起来记为s(n,k),例如s(16,16)=123456789ABCDEF10, s(5,2)=11011100101。现在对于给定的n和字符串t,我们想知道是否存在一个k(2 ≤ k ≤ 16),使得t是s(n,k)的子串。
输入描述:
第一行一个整数n(1 ≤ n ≤ 50,000)。
第二行一个字符串t(长度 ≤ 1,000,000)
输出描述:
“yes"表示存在满足条件的k,否则输出"no”
示例1
输入
8
01112
输出
yes
这道题直接套KMP模板就行,没有太多拐弯抹角的东西。
#include<bits/stdc++.h>
using namespace std;
char jz[18]="0123456789ABCDEF";
string t, s="";
void zh(int n, int k){
string ss;
while(n>0){
if(n%k!=0){
ss+=jz[n%k];
}
else ss+=jz[0];
n/=k;
}
reverse(ss.begin(), ss.end());
s += ss;
}
void get_next(string t, int*next){
int i=0;
int j=-1;
next[0]=-1;
while(i<=t.length()){
if(t[i]==t[j]||j==-1){
j++, i++;
next[i]=j;
}
else{
j=next[j];
}
}
}
bool kmp(string s, string t){
int next[t.length()+5];
get_next(t, next);
int i=0;
int j=0;
while(j<t.length() && i<s.length()){
if(t[j]==s[i]||j==0){
j++, i++;
}
else{
j = next[j];
}
}
if(j==t.length()){
return true;
}
return false;
}
int main()
{
int N;
cin>>N>>t;
for(int k=2; k<=16; k++){
s="";
for(int n=1; n<=N; n++){
zh(n, k);
}
// cout<<s<<endl;
if(kmp(s, t)){
cout<<"yes";
return 0;
}
}
cout<<"no";
return 0;
}
例一:Youhane Assembler
牛客题目链接
题意:输入多个字符串,挑选两个字符串s1,s2。
判断s1的后缀字母与s2的前缀字母有多少个字符能匹配。
eg:s1=“ABCDE” s2=“CDEFG”
ps:它们能匹配的字符有3个为"CDE"。
eg: s1=“CDEFG” s2=“ABCDE”
ps:它们能匹配的字符有0个,因为s2字符串中没有G。
运用KMP特性
在KMP里我们了解到,next数组能够将一个字符串前后缀进行匹配,从而达到避免字符串匹配的时候重复判断的效果。
在题目中,我们可以利用next数组匹配字符串前后缀的功能来实现s1与s2的匹配。
解题分析
①、将s1与s2结合为一个字符串s
s=s2+"#"+s1
(ps:s2要前缀,s1要后缀,在中间加上"#"防止s2与s1“越界匹配”)
②、判断字符串s的前缀与后缀有ans个字符能匹配成功。
ans = next[s.length()]
#include<bits/stdc++.h>
using namespace std;
string str[300005];
void get_next(string s, int * next){
int i=0;
int j=-1;
next[0]=-1;
while(i<s.length()){
if(s[i]==s[j]||j==-1){
i++, j++;
next[i]=j;
}
else{
j = next[j];
}
}
}
int main()
{
int n;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1; i<=n; i++)
cin>>str[i];
int m;
cin>>m;
for(int i=1; i<=m; i++){
int q1, q2;
cin>>q1>>q2;
string s = str[q2]+"#"+str[q1];
int len=s.length();
if(q1==q2){
cout<<str[q1].length()<<endl;
}
else{
int next[s.length()+5];
get_next(s, next);
cout<<next[len]<<endl;
}
}
return 0;
}
现在初次接触这种题型,往后遇到KMP题型会陆续添上。
希望将自己的学习经验分享给有需要的人。
我是小郑,一个不怎么会的小白