Manacher模板,kmp,扩展kmp,最小表示法模板
// Manacher算法,很好用。
char s[2*N]; //储存临时串 int save[2*N];//中间记录 int Manacher(char tmp[]) { int len=strlen(tmp); int cnt=0; for(int i=0;i<len;i++) { s[cnt++]='#'; s[cnt++]=tmp[i]; } s[cnt++]='#'; memset(save,0,sizeof(save)); int a=0,p=0; int mx=1; for(int i=1;i<cnt-1;i++) { if(i>=p) { int num=1; while(i+num<cnt&&i-num>=0&&s[i+num]==s[i-num]) { num++; } p=i+num-1; //能到达的最远位置 a=i; save[i]=num-1; //从这个位置出发最长的回文 if(save[i]==0) continue; if(s[i]=='#') { if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1); } else { if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1; } } else { int j=2*a-i; if( i+save[j] < p) { save[i]=save[j]; if(save[i]==0) continue; if(s[i]=='#') { if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1); } else { if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1; } } else { int k=2*i-p; while(p+1<cnt&&k-1>=0&&s[p+1]==s[k-1]) { p++; k--; } a=i; save[i]=p-i; if(save[i]==0) continue; if(s[i]=='#') { if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1); } else { if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1; } } } } return mx; }
kmp,扩展kmp
// 感觉kmp可以理解。 #define N 100010 int s[N]; int next[N]; int t[N]; int main() { //freopen("//home//chen//Desktop//ACM//in.text","r",stdin); //freopen("//home//chen//Desktop//ACM//out.text","w",stdout); int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",s+i); for(int i=0;i<m;i++) scanf("%d",t+i); ///////////////求next int j=0; next[0]=0; for(int i=1;i<m;i++) { while(j!=0&&t[j]!=t[i]) j=next[j-1]; if(t[j]==t[i]) j++; next[i]=j; } ///////////////////// j=0; int ans=-1; for(int i=0;i<n;i++) { while(j!=0&&s[i]!=t[j]) j=next[j-1]; if(s[i]==t[j]) j++; if(j==m) { ans=i+1-m+1; break; } } /////////////////// if(ans==-1) printf("-1\n"); else printf("%d\n",ans); } return 0; } // 扩展kmp。 #defien N 100100 int next[N],sum[N];// sum用来记录 void build(char s[]) { memset(next,0,sizeof(next)); int p=0,a=0; next[0]=len; for(int i=1;i<len;i++) { if(i+next[i-a]-1<p) { next[i]=next[i-a]; } else { int k=p-i; while(p+1<len && s[p+1]==s[k+1]) { p++; k++; } p=max(p,i); next[i]=k+1; a=i; } } } void extend_kmp(char s[],char t[])//求从s到t上的最大前缀 { memset(sum,0,sizeof(sum)); int p=-1,a=0; for(int i=0;i<len;i++) { if(i+next[i-a]-1<p) { sum[i]=next[i-a]; } else { int k=p-i; while(p+1<len && s[p+1]==t[k+1]) { p++; k++; } p=max(p,i); sum[i]=k+1; a=i; } } }
最小表示法
int mistr(char s[],int len) //输入一串字符,返回最小表示法的起始位置 { int i=0,j=1,k=0; while(i<len&&j<len&&k<len) { if(s[i+k]==s[j+k]) { k++; } else { if(s[i+k] > s[j+k]) i=i+k+1; if(s[i+k] < s[j+k]) j=j+k+1; k=0; if(i==j) j++; } } return min(i,j); }