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題型會陸續添上。
希望將自己的學習經驗分享給有需要的人。
我是小鄭,一個不怎麼會的小白