题目描述
知识点
KMP算法nex
数组的理解
实现
码前思考
- 这道题目主要考察的是对于
nex
数组的理解,可以将这道题目看作是对i = len-1
与j =len-2
的字符串匹配过程。唯一不同是这里不论是s[i] == s[j+1]
还是s[i] != s[j+1]
都要进行回退,直到不能再回退为止。
代码实现
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 4e5+10;
int nex[maxn];
char s[maxn];
vector<int> res;
void getNex(){
int len = strlen(s);
nex[0] = -1;
int j = -1;
for(int i=1;i<len;i++){
while(j!=-1 && s[i] != s[j+1]){
j = nex[j];
}
if(s[i] == s[j+1]){
j++;
}
nex[i] = j;
}
}
int main(){
while(scanf("%s",s) != EOF){
res.clear();
//首先是获取nex
getNex();
int len = strlen(s);
//接下来是对最后一位进行匹配,同时不断回退
//此时的j=len-2,i=len-1
int i = len-1;
int j = len-2;
while(j != -1){
if(s[i] == s[j+1]){
//记录长度
res.push_back(j+1+1);
}
//同时继续进行回退
j = nex[j];
}
if(s[i] == s[j+1]){
res.push_back(j+1+1);
}
sort(res.begin(),res.end());
for(int i=0;i<res.size();i++){
printf("%d",res[i]);
if(i!=res.size()-1){
printf(" ");
}else{
printf("\n");
}
}
}
return 0;
}
码后反思
- 需要记住的就是
nex[i]
表示字符串s[0...i]
的最长真前后缀的下标。一定要理解nex
数组表示的含义。