关于字符串的AC自动机,KMP,Trie树,后缀数组。
KMP是基础。当一个字符串与模式串匹配的时,若失配,利用前面匹配的信息,利用三部分连等关系。可以滑动的“恰如其分”。
Next数组的求法:
若此时求的是next[i]的数值,j位置之前的与从i开始后j-1个字符都是匹配的,若s[i]==s[j] 那么next[++i]=++j; 若不相等可以j=next[j]滑动回去。
OK,那么什么时候匹配串滑动?我们设定next[0]=-1,当一直回溯到0还不匹配就滑动吧。
发一道模板题 HDU 1686
#include<algorithm>
#include<iostream>
#include<iterator>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<map>
#define inf (1<<30)
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=10+100;
int N,M;
#define N 30+10000
int next[N];
void getNext(char *s)
{
int i = 0, j = -1;
next[0] = -1;
int len=strlen(s);
while(i != len)
{
if(j == -1 || s[i] == s[j])
{
++i,++j;
if(s[i]!=s[j])
next[i] =j;
else
next[i]=next[j];
}
else
j = next[j];
}
}
int KMP(char *s1, char *s2)
{
int i=0,j=0;
int len1=strlen(s1),len2=strlen(s2);
int res=0;
while(i<len2)
{
if(j==-1 || s1[j]==s2[i])
i++,j++;
else
j=next[j];
if(j==len1)
res++,j=next[j];
}
return res;
}
char s1[11000],s2[1100000];
int main()
{
int T;
scanf("%d",&T);
getchar();
while(T--){
gets(s1);gets(s2);
getNext(s1);
printf("%d\n",KMP(s1,s2));
}
return 0;
}
原文:http://blog.csdn.net/gg_gogoing/article/details/41214401