字符串算法复习

字符串算法复习

 

声明:

由于本人较弱,并不能保证以下内容的100%正确

欢迎大佬来挑错

Hash

自然溢出hash

扫描二维码关注公众号,回复: 83871 查看本文章

单模数hash

双模数hash

挂链hash

Trie

普通Trie

可持久化Trie

Kmp

扩展Kmp(不会)

后缀数组

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cassert>
 5 using namespace std;
 6 const int maxn=1000009;
 7 
 8 int n;
 9 
10 char s[maxn];
11 int sa[maxn],c[maxn];
12 int t1[maxn<<1],t2[maxn<<1];
13 void BuildSA(int m){
14     int *x=t1,*y=t2;
15     
16     for(int i=1;i<=m;++i)c[i]=0;
17     for(int i=1;i<=n;++i)c[x[i]=s[i]]++;
18     for(int i=2;i<=m;++i)c[i]+=c[i-1];
19     for(int i=n;i>=1;--i)sa[c[x[i]]--]=i;
20     
21     for(int k=1;k<n;k<<=1){
22         int p=0;
23         for(int i=n-k+1;i<=n;++i)y[++p]=i;
24         for(int i=1;i<=n;++i)if(sa[i]-k>0)y[++p]=sa[i]-k;
25         
26         for(int i=1;i<=m;++i)c[i]=0;
27         for(int i=1;i<=n;++i)c[x[y[i]]]++;
28         for(int i=2;i<=m;++i)c[i]+=c[i-1];
29         for(int i=n;i>=1;--i)sa[c[x[y[i]]]--]=y[i];
30         
31         swap(x,y);
32         x[sa[1]]=p=1;
33         for(int i=2;i<=n;++i){
34             if((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+k]==y[sa[i-1]+k]))x[sa[i]]=p;
35             else x[sa[i]]=++p;
36         }
37         if(p>=n)break;
38         m=p;
39     }
40 }
41 
42 int main(){
43     scanf("%s",s+1);
44     n=strlen(s+1);
45     BuildSA(10000);
46     
47     for(int i=1;i<=n;++i)printf("%d ",sa[i]);
48     return 0;
49 }

后缀自动机

 Menci的链接

https://oi.men.ci/suffix-automaton-notes/

写得很清楚

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=1000009;
 6 
 7 
 8 int n;
 9 long long ans=0;
10 char s[maxn];
11 
12 int nn=1,last=1;
13 int par[maxn<<1]={0};
14 int siz[maxn<<1]={0};
15 int dis[maxn<<1]={0};
16 int ch[maxn<<1][26]={0};
17 void BuildSAM(int c){
18     int p=last,np=++nn;
19     last=np;siz[np]=1;dis[np]=dis[p]+1;
20     
21     for(;(p!=0)&&(!ch[p][c]);p=par[p])ch[p][c]=np;
22     if(!p){
23         par[np]=1;
24     }else{
25         int q=ch[p][c];
26         if(dis[q]==dis[p]+1){
27             par[np]=q;
28         }else{
29             int nq=++nn;
30             for(int i=0;i<26;++i)ch[nq][i]=ch[q][i];
31             dis[nq]=dis[p]+1;
32             par[nq]=par[q];
33             par[q]=par[np]=nq;
34             for(;ch[p][c]==q;p=par[p])ch[p][c]=nq;
35         }
36     }
37 }
38 
39 int c[maxn<<1];
40 int sa[maxn<<1];
41 void Dp(){
42     for(int i=1;i<=nn;++i)c[dis[i]]++;
43     for(int i=1;i<=nn;++i)c[i]+=c[i-1];
44     for(int i=1;i<=nn;++i)sa[c[dis[i]]--]=i;
45     for(int i=nn;i>=1;--i){
46         int x=sa[i];
47         siz[par[x]]+=siz[x];
48         if(siz[x]!=1){
49             ans=max(ans,1LL*siz[x]*dis[x]);
50         }
51     }
52 }
53 
54 int main(){
55     scanf("%s",s+1);
56     n=strlen(s+1);
57     for(int i=1;i<=n;++i)BuildSAM(s[i]-'a');
58     
59     Dp();
60     cout<<ans<<endl;
61     return 0;
62 }

广义后缀自动机

2780: [Spoj]8093 Sevenk Love Oimaster

4566: [Haoi2016]找相同字符

AC自动机

2754: [SCOI2012]喵星球上的点名

manacher

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=30000000;
 6 
 7 int n;
 8 int ans=0;
 9 char T[maxn];
10 
11 char s[maxn];
12 int p[maxn];
13 void Manacher(int n){
14     int mxpla=0,mxlen=0;
15     for(int i=1;i<=n;++i){
16         if(mxpla+mxlen>i){
17             p[i]=min(mxpla+mxlen-i,p[2*mxpla-i]);
18         }
19         while(s[i-p[i]]==s[i+p[i]])++p[i];
20         ans=max(ans,p[i]*2-1); 
21         if(i+p[i]>mxpla+mxlen){
22             mxpla=i;mxlen=p[i];
23         }
24     }
25 }
26 
27 int main(){
28     scanf("%s",T+1);
29     n=strlen(T+1);
30     int len=0;
31     s[++len]='*';
32     for(int i=1;i<=n;++i){
33         s[++len]=T[i];
34         s[++len]='*';
35     }
36     s[++len]='#';
37     Manacher(len);
38     
39     cout<<(ans>>1)<<endl;
40     return 0;
41 }

猜你喜欢

转载自www.cnblogs.com/zzyer/p/8965981.html