http://tjuacm.chaosheng.top/problem.php?id=1259
https://vjudge.net/problem/HDU-2594
字符串匹配KMP,太不熟练了,这个算法一直一知半解。
参考:
https://blog.csdn.net/weixin_44606952/article/details/97654887?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.baidujs&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.baidujs
先发一个暴力,WA有没有处理好的情况
如
llljs
mkllll
会输出0,但是实际应该是3。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 50010;
int main(){
string s1, s2;
while(cin >> s1 >> s2){
//cin >> s2;
int n = s1.size();
int m = s2.size();
if(n == 0 || m == 0){
printf("0\n");
continue;
}
int i = 0, j = 0;
int len = 0;
while(i < n && j < m){
if(s1[i] == s2[j]){
i++;
j++;
len++;
}else{
i = 0;
j++;
len = 0;
}
//printf("i = %d j = %d len = %d \n", i, j, len);
}
if(j == m && len != 0){
printf("%s %d\n", s1.substr(0, len).c_str(), len);
}else{
printf("0\n");
}
}
return 0;
}AC代码,用到KMP
KMP的next数组讲解 https://www.bilibili.com/video/BV1jb411V78H?from=search&seid=4819368457483381295
实现 https://blog.csdn.net/loterior/article/details/79104602
这个题是KMP的应用。本质上就是找前一个字符串的前缀和后一个字符串的后缀相同的串,使用 KMP 进行匹配时,注意当模式串 s1 到达结尾时,需要更新指针位置,返回值也需要返回前缀位置
kmp就是一个不断匹配的过程,但是当第一个字符串(就是要求next数组的)长度小于第二个字符串时,会出现匹配突然断了的情况,这个时候的,就要j=next[j],重新找到最近的点继续匹配,一直匹配到最后,既然要匹配到最后,那么肯定能够知道前缀和后缀的最大匹配,也就是最后的j值。
参考 https://blog.csdn.net/u011815404/article/details/87983299
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 50010;
int nextt[N];
void getNext(string s){
int n = s.size();
int i = 0, j = -1;
nextt[i] = j;
while(i < n){
if(j == -1 || s[i] == s[j]){
i++;
j++;
nextt[i] = j;
}else{
j = nextt[j];
}
}
}
int kmp(string s2, string s1){
getNext(s1);
int n = s1.size();
int m = s2.size();
int i = 0, j = 0;
while(i < m && j < n){
if(j == -1 || s2[i] == s1[j]){
i++;
j++;
if(j == n && i != m){//当模式串到达结尾时,回到指定位置
j = nextt[j];
}
}else{
j = nextt[j];
}
}
return j; //返回前缀的位置
}
int main(){
string s1, s2;
while(cin >> s1 ){
cin >> s2;
int n = s1.size();
int m = s2.size();
if(n == 0 || m == 0){
printf("0\n");
continue;
}
int res = kmp(s2, s1);
if(res != 0){
printf("%s %d\n", s1.substr(0, res).c_str(), res);
}else{
printf("0\n");
}
}
return 0;
}
京公网安备 11010502036488号