后缀数组
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <limits> #include <set> #include <map> using namespace std; #define SZ 666666 int n,sa[SZ],t[SZ],rank[SZ],qzh[SZ],tmpsa[SZ],tmpr[SZ],h[SZ]; char s[SZ]; bool same(int a,int b,int p) {return t[a]==t[b]&&t[a+p]==t[b+p];} void getsa(int n,int m=233) { for(int i=0;i<n;i++) rank[i]=s[i], ++qzh[rank[i]]; for(int i=1;i<m;i++) qzh[i]+=qzh[i-1]; for(int i=n-1;i>=0;i--) sa[--qzh[rank[i]]]=i; for(int j=1;j<=n;j<<=1) { int cur=-1; for(int i=n-j;i<n;i++) tmpsa[++cur]=i; for(int i=0;i<n;i++) if(sa[i]>=j) tmpsa[++cur]=sa[i]-j; for(int i=0;i<n;i++) tmpr[i]=rank[tmpsa[i]]; for(int i=0;i<m;i++) qzh[i]=0; for(int i=0;i<n;i++) ++qzh[tmpr[i]]; for(int i=1;i<m;i++) qzh[i]+=qzh[i-1]; for(int i=n-1;i>=0;i--) t[i]=rank[i], sa[--qzh[tmpr[i]]]=tmpsa[i]; m=0; for(int i=0;i<n;i++) rank[sa[i]]=(i>0&&same(sa[i],sa[i-1],j))?m:++m; ++m; } for(int i=0;i<n;i++) rank[sa[i]]=i; } void geth(int n) { int p=0; for(int i=0;i<n;i++) { if(p) --p; int ls=sa[rank[i]-1]; while(s[ls+p]==s[i+p]) p++; h[rank[i]]=p; } } int main() { scanf("%s",s); n=strlen(s); getsa(n+1); geth(n); for(int i=1;i<=n;i++) printf("%d ",sa[i]+1); putchar(10); for(int i=2;i<=n;i++) printf("%d ",h[i]); }
hash+kmp(搭配风味更佳)
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <algorithm> using namespace std; #define SZ 2333333 typedef long long ll; ll MOD=1000000007,cm[SZ],cmn[SZ]; ll qp(ll a,ll b) { ll ans=1; while(b) { if(b&1) ans=ans*a%MOD; a=a*a%MOD; b>>=1; } return ans; } struct HashKMP { char s[SZ+1]; int n; ll hash[SZ+1]; void pre() { n=strlen(s); for(int i=n-1;i>=0;i--) hash[i]=(hash[i+1]+cm[n-1-i]*(s[i]-‘a‘+1)%MOD)%MOD; } ll ghash(int l,int r) { return ((hash[l]-hash[r+1])*cmn[n-1-r]%MOD+MOD)%MOD; } int next[SZ+3]; void gnext() { next[0]=-1; int j=-1; for(int i=1;s[i];i++) { while(j!=-1&&s[i]!=s[j+1]) j=next[j]; if(s[i]==s[j+1]) ++j; next[i]=j; } } void kmp(char* a) { int j=-1; for(int i=0;a[i];i++) { while(j!=-1&&s[j+1]!=a[i]) j=next[j]; if(s[j+1]==a[i]) ++j; //do sth printf("%d w %d\n",i,j); } } }ha; void getcm() { cm[0]=cmn[0]=1; ll gg=qp(31,MOD-2); for(int i=1;i<=1234567;i++) cm[i]=cm[i-1]*31%MOD; for(int i=1;i<=1234567;i++) cmn[i]=cmn[i-1]*gg%MOD; } char b[SZ+3]; int main() { getcm(); scanf("%s",ha.s); ha.pre(); scanf("%s",b); ha.gnext(); ha.kmp(b); }
后缀自动机+序列自动机
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <limits> #include <set> #include <map> using namespace std; int MOD=998244353; #define SZ 4008 #define S 26 //字符集 struct AM { int rot,ch[SZ][S],C,cnt[SZ]; }; struct SeqAM: public AM { int par[SZ],lst[S]; SeqAM() { C=rot=1; for(int i=0;i<S;i++) lst[i]=rot; } void ins(char c) { ++C; par[C]=lst[c]; for(int i=0;i<S;i++) { for(int g=lst[i];g&&!ch[g][c];g=par[g]) ch[g][c]=C; } lst[c]=C; } void getcnt() { for(int i=1;i<=C;i++) cnt[i]=1; for(int i=C;i>=1;i--) { for(int j=0;j<S;j++) cnt[i]+=cnt[ch[i][j]], cnt[i]%=MOD; } } }SeqA,SeqB; struct SufAM: public AM { int ml[SZ],fail[SZ],lst,cl,qzh[SZ],od[SZ]; SufAM() {C=lst=rot=1; cl=0;} void ins(char c) { int x=++C,len=++cl,p=lst; lst=x; ml[x]=len; for(;p&&!ch[p][c];p=fail[p]) ch[p][c]=x; if(!p) fail[x]=rot; else if(ml[ch[p][c]]==ml[p]+1) fail[x]=ch[p][c]; else { int chh=ch[p][c],cm=++C; ml[cm]=ml[p]+1; fail[cm]=fail[chh]; for(int i=0;i<S;i++) ch[cm][i]=ch[chh][i]; fail[chh]=fail[x]=cm; for(;ch[p][c]==chh;p=fail[p]) ch[p][c]=cm; } } void getcnt() { for(int i=0;i<SZ;i++) qzh[i]=0; for(int i=1;i<=C;i++) qzh[ml[i]]++; for(int i=1;i<SZ;i++) qzh[i]+=qzh[i-1]; for(int i=1;i<=C;i++) od[qzh[ml[i]]--]=i; for(int i=1;i<=C;i++) cnt[i]=1; for(int i=C;i>=1;i--) { for(int j=0;j<S;j++) cnt[od[i]]+=cnt[ch[od[i]][j]], cnt[od[i]]%=MOD; } } }SufA,SufB;
AC自动机
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <limits> #include <set> #include <map> using namespace std; #define SZ 1000099 int rot=1,ch[SZ][29],fail[SZ],cnt[SZ],e=1; void insert(char* s) { int cur=rot; for(int i=0;s[i];i++) { int c=s[i]-‘a‘; if(!ch[cur][c]) ch[cur][c]=++e; cur=ch[cur][c]; } cnt[cur]++; } int qs[SZ],h=0,t=0; void bfail() { h=t=0; fail[rot]=rot; for(int i=0;i<26;i++) { if(!ch[rot][i]) { ch[rot][i]=rot; continue; } fail[ch[rot][i]]=rot; qs[t++]=ch[rot][i]; } while(h!=t) { int cur=qs[h++]; for(int c=0;c<26;c++) { if(!ch[cur][c]) ch[cur][c]=ch[fail[cur]][c]; else { fail[ch[cur][c]]=ch[fail[cur]][c]; qs[t++]=ch[cur][c]; } } } } int match(char* s) { int cur=rot,ans=0; for(int i=0;s[i];i++) { int c=s[i]-‘a‘; cur=ch[cur][c]; for(int f=cur;f!=rot;f=fail[f]) ans+=cnt[f], cnt[f]=0; } return ans; } int n,T; char str[SZ]; int main() { scanf("%d",&T); while(T--) { rot=e=1; memset(ch,0,sizeof(ch)); memset(fail,0,sizeof(fail)); memset(cnt,0,sizeof(cnt)); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",str); insert(str); } bfail(); scanf("%s",str); printf("%d\n",match(str)); } }
manacher
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> using namespace std; #define SZ 666666 int p[SZ]; char str[SZ]; void manacher() { int ml=0,id; for(int i=0;str[i];i++) { if(ml>i) p[i]=min(p[2*id-i],p[id]+id-i); else p[i]=1; while(i>=p[i]&&str[i+p[i]]==str[i-p[i]]) ++p[i]; if(p[i]+i>ml) ml=p[i]+i, id=i; } } char s[SZ]; void init() { str[0]=‘$‘; int n=1; for(int i=0;s[i];i++) str[n++]=s[i], str[n++]=‘$‘; str[n]=0; } int main() { while(gets(s)) { if(!s[0]) continue; init(); manacher(); int ans=0; for(int i=0;str[i];i++) ans=max(ans,p[i]); printf("%d\n",ans-1); } return 0; }
回文树
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <math.h> #include <limits> #include <set> #include <map> using namespace std; struct PTree { #define SZ 666666 int ch[SZ][26],len[SZ],fail[SZ],cnt[SZ],s[SZ],cl,an,lst; int addn(int l) {len[an]=l; return an++;} PTree() { cl=an=lst=0; memset(ch,0,sizeof(ch)); addn(0); addn(-1); fail[0]=1; s[0]=-233; } int gfail(int x,int l) { while(s[l-len[x]-1]!=s[l]) x=fail[x]; return x; } void add(int c) { s[++cl]=c; int cp=gfail(lst,cl); if(!ch[cp][c]) { int nn=addn(len[cp]+2); fail[nn]=ch[gfail(fail[cp],cl)][c]; ch[cp][c]=nn; } cnt[lst=ch[cp][c]]++; } void getcnt() { for(int i=an-1;i>=2;i--) cnt[fail[i]]+=cnt[i]; } }pt; char s[SZ]; int main() { scanf("%s",s); for(int i=0;s[i];i++) pt.add(s[i]-‘a‘); pt.getcnt(); long long ans=0; for(int i=2;i<=pt.an;i++) ans=max(ans,pt.len[i]*(long long)pt.cnt[i]); printf("%lld\n",ans); }
本来这篇文章是想放一些字符串题目,在前面整一下模板...没想到整了这么长...就下一篇文章放题目好了。
时间: 2024-11-16 11:24:12