KMP
KMP
inline void get_next(char *a) { int n=strlen(a+1); next[1]=0; for(int i=2,j=0;i<=n;++i) { while(j>0&&a[i]!=a[j+1]) j=next[j]; if(a[i]==a[j+1]) ++j; next[i]=j; } } inline void KMP(char *a,char *b)//a是文本串,b是模式串 { int n=strlen(a+1); int m=strlen(b+1); for(int i=1,j=0;i<=n;++i) { while(j>0&&(j==m||a[i]!=b[j+1])) j=next[j]; if(a[i]==b[j+1]) ++j; f[i]=j; if(f[i]==m) cout<<i-m+1<<endl; } }
安利一道比较好的对next数组理解的题
[POI2006]OKR-Periods of Words
测试点信息源代码 源代码 复制 #include<bits/stdc++.h> #define db double #define RE register #define ll long long #define P=1000000009 #define INF 1000000000 #define get(x) x=read() #define pair<ll,int> PLI #define pb(x) push_back(x) #define pair<int,int> PII #define ull unsigned long long #define put(x) printf("%d\n",x) #define getc(a) scanf("%s",a+1) #define putl(x) printf("%lld\n",x) #define rep(i,x,y) for(RE int i=x;i<=y;++i) #define fep(i,x,y) for(RE int i=x;i>=y;--i) #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y) using namespace std; const int N=1e6+10; int next[N],n,f[N];//f[i]表示以i为结尾的后缀与从1开始的前缀最短的匹配长度. char c[N]; inline int read() { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline void get_next() { int j=0;next[1]=0;f[1]=n; rep(i,2,n) { while(j>0&&c[i]!=c[j+1]) j=next[j]; if(c[i]==c[j+1]) ++j; next[i]=j; if(next[i]==0) f[i]=n; else if(f[next[i]]==n) f[i]=next[i]; else f[i]=f[next[i]]; } } int main() { // freopen("1.in","r",stdin); get(n);getc(c); get_next(); ll ans=0; rep(i,1,n) { if(f[i]==n) continue; else ans+=i-f[i]; } //rep(i,1,n) cout<<i<<' '<<next[i]<<endl; putl(ans); return 0; }
[NOI2014]动物园
这个题真的是头疼....
调了尽两个小时尽然是自己模数取错了.....
我们发现暴力跳next是不行的,那我们思考怎么优化。
我们可以想到我们只要一直维护j<=i/2即可。
#include<bits/stdc++.h> #define db double #define RE register #define ll long long #define P 1000000007 #define INF 1000000000 #define get(x) x=read() #define pair<ll,int> PLI #define pb(x) push_back(x) #define pair<int,int> PII #define ull unsigned long long #define put(x) printf("%d\n",x) #define getc(a) scanf("%s",a+1) #define putl(x) printf("%lld\n",x) #define rep(i,x,y) for(RE int i=x;i<=y;++i) #define fep(i,x,y) for(RE int i=x;i>=y;--i) #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y) using namespace std; const int N=1000010; int next[N],g[N]; char c[N]; ll ans=1; inline int read() { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline void get_next() { int n=strlen(c+1); int j=0;g[1]=0;g[0]=-1; rep(i,2,n) { while(j>0&&c[i]!=c[j+1]) j=next[j]; if(c[i]==c[j+1]) ++j; next[i]=j;g[i]=g[j]+1; } } inline void get_num() { int n=strlen(c+1); int j=0; rep(i,2,n) { while(j>0&&c[i]!=c[j+1]) j=next[j]; if(c[i]==c[j+1]) ++j; while((j<<1)>i) j=next[j]; ans=(ans*(ll)(g[j]+2))%P; } } int main() { freopen("1.in","r",stdin); int get(T); while(T--) { memset(g,0,sizeof(g)); getc(c);get_next(); ans=1; get_num(); putl(ans); } return 0; }