KMP,快速字符串匹配,其实也是一种对暴力算法的优化(但是这优化竟如此强大且著名一直沿用至今tql Orz %%%)这是板子题
这是代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
const int maxn=1000000+5;
using namespace std;
string s,p;
int nxtpos[maxn],lcpp[maxn],nxtpos0[maxn];//nxtpos0为未优化版nxtpos数组
void getnxt()
{
nxtpos[0]=-1;
nxtpos0[0]=-1;
int len = p.length();
int j=0,k=-1;
while(j <= len - 1)
{
if(k==-1||p[j]==p[k])
{
j++;
k++;
nxtpos0[j]=k;
if(p[j]!=p[k])
{
nxtpos[j] = k;
}
else
{
nxtpos[j] = nxtpos[k];
}
}
else
{
k = nxtpos0[k];
}
}
}
void kmp()
{
int i=0,j=0;
int slen=s.length();
int plen=p.length();
while(i < slen)
{
if(j == -1||p[j] == s[i])
{
i++;
j++;
}
else
{
j=nxtpos0[j];
}
if(j==plen)
{
cout<<i-j+1<<"\n";
i=i-j+1;
j=0;
}
}
}
int main()
{
cin>>s>>p;//getline太垃圾了(不是
getnxt();
kmp();
for(int i=0;i<p.length();i++)
{
lcpp[i]=nxtpos0[i+1];
printf("%d ",lcpp[i]);
}
return 0;
}
优化的核心思想是当出现s与p失配的情况后利用nxtpos[]数组实现只移动p而不移动s上的位置指针i,所谓nxtpos数组,nxtpos[i]表示在字符串p上的位置i之前(不包括i)的字串中最大公共前缀后缀的长度(如p=ABCAB,nxtpos[4]=1,最大公共前缀后缀就是’A’。
求nxtpos的过程大概 就是个p与自己匹配的过程,个人理解,k是在完成一个不断跑前缀的任务,用来计算nxtpos[j],有一个小优化就是p[j]==p[k]的时候,由于原来的算法中k就是nxtpos[j],会导致s[i]与p[j]失配后还是会和p[k]失配,这时就继续递归使nxtpos[p]=nxtpos[k]。
然后nxtpos就求好了。
然后用nxtpos匹配,失配时j=nxtpos[j],就完了。
就完了!
经典算法tql!