前缀函数
给定一个长度为 n n n 的字符串 s s s,其前缀函数被定义为一个长度为 n n n 的数组 π \pi π,其中 π [ i ] \pi[i] π[i] 定义为最长真前缀,若没有最长真前缀,则 π [ i ] = 0 \pi[i]=0 π[i]=0. (默认下标从 0 0 0 开始)
O ( N ) O(N) O(N) 求前缀函数
char p[N];
int nxt[N];
void getnxt()
{
int i,j;
for(i=1;p[i];++i)
{
j=nxt[i-1]; j是最长真前缀的长度
while(j>0&&p[i]!=p[j])
j=nxt[j-1];
if(p[i]==p[j]) ++j;
nxt[i]=j;
}
}
KMP实现,时间复杂度 O ( N + M ) O(N+M) O(N+M)
八股文模板,必背
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#define me(x,y) memset(x,y,sizeof x)
#define rep(i,x,y) for(i=x;i<=y;++i)
#define repf(i,x,y) for(i=x;i>=y;--i)
#define lowbit(x) -x&x
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define f first
#define s second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> PII;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int N=1e5+10,M=1e6+10;
int n,m;
char s[M],p[N];
int nxt[N];
void getnxt()
{
int i,j;
rep(i,1,n-1)
{
j=nxt[i-1];
while(j>0&&p[i]!=p[j]) j=nxt[j-1];
if(p[i]==p[j]) ++j;
nxt[i]=j;
}
}
void kmp()
{
int i,j;
i=0,j=0;
while(i+n-j-1<m)
{
while(j<n&&p[j]==s[i]) ++i,++j;
if(j==n) printf("%d ",i-n);
if(!j)
{
++i;
continue;
}
j=nxt[j-1];
}
}
int main()
{
int i,j;
n=read(),scanf("%s",p);
m=read(),scanf("%s",s);
getnxt();
kmp();
return 0;
}
例题1
本题是
K
M
P
KMP
KMP ,从非起点开始进行
K
M
P
KMP
KMP
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#define me(x,y) memset(x,y,sizeof x)
#define rep(i,x,y) for(i=x;i<=y;++i)
#define repf(i,x,y) for(i=x;i>=y;--i)
#define lowbit(x) -x&x
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define f first
#define s second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> PII;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int N= 1e6+10;
int n;
string s,ans;
int nxt[N];
int kmp()
{
int len=s.size(),len_=ans.size(),i,j;
rep(i,0,len) nxt[i]=0;
rep(i,1,len-1)
{
j=nxt[i-1];
while(j>0&&s[i]!=s[j]) j=nxt[j-1];
if(s[i]==s[j]) ++j;
nxt[i]=j;
}
i=max(len_-len,0),j=0;
while(i<len_&&j<len)
{
while(i<len_&&j<len&&s[j]==ans[i]) ++i,++j;
if(i==len_||j==len) break;
if(!j)
{
++i;
continue;
}
j=nxt[j-1];
}
return j;
}
int main()
{
int i,j;
n=read();
cin>>ans;
rep(i,1,n-1)
{
cin>>s;
auto pos=kmp();
if(pos==s.size()) continue;
else ans+=s.substr(pos,s.size()-1-pos+1);
}
cout<<ans;
return 0;
}