这里的求next有两种写法,思路是一样的。
作者喜欢用第一种:
void calnext(string &s2) {
nt[0]=-1;
nt[1]=0;
for(int i=2;i<s2.size();i++) {
int t = i-1;
while(t > 0 && s2[nt[t]] != s2[i-1]) {
t=nt[t];
}
//for (int i=0 ;i
// cout << ne[i] << " ";
//}
nt[i]=nt[t]+1;
}
}
第二种求next写法:
int i=2,cn=0;
while (i<tstr.size()) {
if (tstr[i-1]==tstr[cn]) {
ne[i++]= ++cn;
}else if (cn>0){
cn=ne[cn];
}else {
ne[i++]= 0;
}
}
整体KMP写法(next求法+匹配)
//kmp算法
#include
using namespace std;
const int M = 1e5+5;
int nt[M];
void calnext(string &s2) {
nt[0]=-1;
nt[1]=0;
for(int i=2;i<s2.size();i++) {
int t = i-1;
while(t > 0 && s2[nt[t]] != s2[i-1]) {
t=nt[t];
}
//for (int i=0 ;i
// cout << ne[i] << " ";
//}
nt[i]=nt[t]+1;
}
}
void kmpnow(string &a,string &b){
// cout<<"到达"<<'\n';
int x=0,y=0;
while (x<a.size()&&y<b.size()) {
if (a[x]==b[y]) {
x++,y++;
}else if (y==0) {
x++;
}else {
y=nt[y];
}
}
if (y==b.size()) {
cout<<x-y<<'\n';
}else {
cout<<"没有找到"<<'\n';
}
}
int main() {
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
string s1,s2;
cin>>s1>>s2;
calnext(s2);
kmpnow(s1,s2);
return 0;
}
无线传输题目
ans = n - next[n]
为什么不能更长呢?
#include
using namespace std;
const int N = 1e6+5;
int ne[N];
string s;
int l;
void calnext() {
ne[0] = -1;
ne[1] = 0;
for (int i=2;i<=l;i++) {//这里多求一个位置
int t = i - 1;
while (t > 0 && s[ne[t]]!=s[i-1]) {
t = ne[t];
}
ne[i]=ne[t]+1;
}
cout<<l - ne[l]<<'\n';//总长减去最后一个值的后一个位置的ne值
}
int main() {
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>l>>s;
calnext();
return 0;
}
题目点击这里
栈+KMP混合使用
first:第一个串中的下标
second:第二个串中的下标
#include
using namespace std;
const int N = 1e6+5;
int ne[N];
string s,tstr;
// vector > st;
int sz=0;
struct st {
int first, second;
// st(int a, int b) : first(a), second(b) {}
// st():first(0),second(0){}
}st1[N];
void calnext() {
ne[0] = -1;
ne[1] = 0;
for (int i=2;i<tstr.size();i++) {
int t = i - 1;
while (t > 0 && tstr[ne[t]]!=tstr[i-1]) {
t = ne[t];
}
ne[i]=ne[t]+1;
}
}
int main() {
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>s>>tstr;
calnext();
int x=0,y=0;
while (x<s.size()) {
if (s[x]==tstr[y]) {
st1[sz].first=x++,st1[sz].second=y++;
sz++;
}else if (y==0) {
st1[sz].first=x++,st1[sz].second=-1;
sz++;
}else {
y = ne[y];
}
if (y==tstr.size()) {
sz-=tstr.size();
if (sz) {
y=st1[sz-1].second + 1;
}else {
y=0;
}
}
}
for (int i=0;i<sz;i++) {
auto &p=st1[i].first;
cout<<s[p];
}
return 0;
}
1367.二叉树中的链表
const int N = 2505;
class Solution {
public:
int n,m,a[N];
int ne[N];
vector<int>h;
bool isSubPath(ListNode* head, TreeNode* root) {
n = cnt(root);
change(head);
m = h.size();
calnext();
return findTF(root,0);
}
bool findTF(TreeNode* root,int i){
if(i == m){
return true;
}
if(root == NULL){
return false;
}
while(i>=0&&root->val!=h[i]){
i=ne[i];
}
return findTF(root->left,i+1)|| findTF(root->right,i+1);
}
int cnt(TreeNode* root){
if(root==NULL){
return 0;
}else{
int l = cnt(root->left);
int r = cnt(root->right);
return l+r;
}
}
void change(ListNode* head){
while(head!=NULL){
h.push_back(head->val);
head=head->next;
}
}
void calnext() {
ne[0] = -1;
ne[1] = 0;
for (int i=2;i<h.size();i++) {
int t = i - 1;
while (t > 0 && h[ne[t]]!=h[i-1]) {
t = ne[t];
}
ne[i]=ne[t]+1;
}
}
};