先写一个在线的多模字符串匹配
O(m+logn)的,按照https://wenku.baidu.com/view/cd7db304e87101f69e31953e.html的思想,很难写
没地方交啊
只能找出是否出现,不能找出出现了几次
要找出现的次数,大概就是二分第一个出现的位置和最后一个出现的位置吧?不确定能不能写
拍了一会没出错,先当做对的好了
1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 using namespace std; 5 string str[1000100],txt; 6 int n; 7 namespace SA 8 { 9 int n,p,m=128,sa[1000100],t1[1000100],t2[1000100],cnt[1000100],*x=t1,*y=t2; 10 int *height=t2,*rk=t1; 11 int st[1000100][21],log2x[1000100],lft[21]; 12 const int log2n=20; 13 void build() 14 { 15 int i,k; 16 n=txt.length(); 17 for(i=0;i<n;i++) cnt[x[i]=txt[i]]++; 18 for(i=1;i<m;i++) cnt[i]+=cnt[i-1]; 19 for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i; 20 for(k=1;k<=n;k<<=1) 21 { 22 p=0; 23 for(i=n-k;i<n;i++) y[p++]=i; 24 for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 25 for(i=0;i<m;i++) cnt[i]=0; 26 for(i=0;i<n;i++) cnt[x[y[i]]]++; 27 for(i=1;i<m;i++) cnt[i]+=cnt[i-1]; 28 for(i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]]=y[i]; 29 swap(x,y);p=0; 30 x[sa[0]]=0; 31 for(i=1;i<n;i++) 32 x[sa[i]]=y[sa[i]]==y[sa[i-1]] 33 &&(sa[i]+k<n?y[sa[i]+k]:0)==(sa[i-1]+k<n?y[sa[i-1]+k]:0) 34 ?p:++p; 35 if(p>=n) break; 36 m=p+1; 37 } 38 for(i=0;i<n;i++) rk[sa[i]]=i; 39 for(i=0,k=0;i<n;i++) 40 { 41 if(k) k--; 42 if(rk[i]) 43 while(sa[rk[i]-1]+k<n&&i+k<n&&txt[sa[rk[i]-1]+k]==txt[i+k]) k++; 44 height[rk[i]]=k; 45 } 46 lft[0]=1;for(i=1;i<=log2n;i++) lft[i]=lft[i-1]<<1; 47 log2x[1]=k=0; 48 for(i=2;i<=1000000;i++) 49 { 50 if(i>=lft[k+1]) ++k; 51 log2x[i]=k; 52 } 53 for(i=0;i<n;i++) st[i][0]=height[i]; 54 for(k=1;k<=log2n;k++) 55 for(i=0;i<n-lft[k]+1;i++) 56 st[i][k]=min(st[i][k-1],st[i+lft[k-1]][k-1]); 57 } 58 int lcp(int l,int r) 59 { 60 if(l==r) return n-l; 61 l=rk[l];r=rk[r];if(l>r) swap(l,r); 62 l++;int k=log2x[r-l+1]; 63 return min(st[l][k],st[r-lft[k]+1][k]); 64 } 65 int lcp(const char *x,int l) 66 { 67 int ans=0; 68 while(*x&&l<n&&*x==txt[l]) ++x,++l,++ans; 69 return ans; 70 } 71 bool find(const string &x) 72 { 73 int l=0,r=n-1,t,mid,mmatch=lcp(x.c_str(),0),mpos=0,m=x.length(),state; 74 while(r>l) 75 { 76 mid=(l+r)/2;t=lcp(sa[mid],mpos); 77 if(t<mmatch) 78 { 79 if(x[t]<txt[sa[mid]+t]) state=-1; 80 //else if(x[t]==txt[sa[mid]+t]) state=0; 81 else state=1; 82 } 83 else 84 { 85 mpos=sa[mid]; 86 while(mmatch<m&&mmatch+mpos<n&&x[mmatch]==txt[mmatch+mpos]) mmatch++; 87 if(mmatch==m) state=0; 88 else if(x[mmatch]<txt[mmatch+mpos]) state=-1; 89 else if(x[mmatch]>txt[mmatch+mpos]) state=1; 90 } 91 if(state<0) r=mid-1; 92 else if(state==0) return 1; 93 else l=mid+1; 94 } 95 return lcp(x.c_str(),sa[l])==m; 96 } 97 } 98 int ans; 99 int main() 100 { 101 int i; 102 cin>>n; 103 for(i=1;i<=n;i++) cin>>str[i]; 104 cin>>txt; 105 SA::build(); 106 //for(i=0;i<SA::n;i++) cout<<SA::sa[i]+1<<' '; 107 for(i=1;i<=n;i++) ans+=SA::find(str[i]); 108 cout<<ans; 109 return 0; 110 }
另一份后缀数组模板
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 char s[1000100]; 6 int n; 7 int sa[1000100],t1[1000100],t2[1000100],cnt[1000100]; 8 int *x=t1,*y=t2,m='z',p; 9 int main() 10 { 11 int i,k; 12 scanf("%s",s+1);n=strlen(s+1); 13 for(i=1;i<=n;i++) cnt[x[i]=s[i]]++; 14 for(i=1;i<=m;i++) cnt[i]+=cnt[i-1]; 15 for(i=n;i>=1;i--) sa[cnt[x[i]]--]=i; 16 for(k=1;k<=n;k<<=1) 17 { 18 //x[i]存上一轮中后缀i的rank 19 p=0; 20 for(i=n-k+1;i<=n;i++) y[++p]=i; 21 for(i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k; 22 //y[i]暂存对第二关键字排序后的rank为i的后缀编号 23 for(i=1;i<=m;i++) cnt[i]=0; 24 for(i=1;i<=n;i++) cnt[x[y[i]]]++; 25 for(i=1;i<=m;i++) cnt[i]+=cnt[i-1]; 26 for(i=n;i>=1;i--) sa[cnt[x[y[i]]]--]=y[i]; 27 28 swap(x,y);p=0; 29 for(i=1;i<=n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p; 30 if(p>=n) break; 31 m=p; 32 } 33 for(i=1;i<=n;i++) printf("%d ",sa[i]); 34 return 0; 35 }
nlog^2n构造简单代码
inline bool cmp(int u,int v) { if(rank[u]!=rank[v]) return rank[u]<rank[v]; int nu,nv; nu= (u+l>len?0:rank[u+l]); nv= (v+l>len?0:rank[v+l]); return nu<nv; } int main() { int i,j,k; scanf("%s",str+1); len=strlen(str+1); for(i=1; i<=len; i++) { rank[i]=str[i]; st[i]=i; } for(l=1; l<=len; l<<=1) { sort(st+1,st+len+1,cmp); tmp[st[1]]=1; for(i=2; i<=len; i++) { tmp[st[i]]=tmp[st[i-1]]+cmp(st[i-1],st[i]); } for(i=1; i<=len; i++) { rank[i]=tmp[i]; } } }