板子汇总
字符串
后缀自动机
P3804 【模板】后缀自动机(SAM)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
struct Suffix_Automaton{
/********** beg **********/
int len[maxn<<1];
int ch[maxn<<1][26];
int link[maxn<<1];
int siz,last;
void init(){
len[0]=0;
for(int i=0;i<26;i++)ch[0][i]=0;
link[0]=-1;
siz=last=0;
}
void extend(int c){
int cur=++siz,p=last;
len[cur]=len[p]+1;
for(int i=0;i<26;i++)ch[cur][i]=0;
for(;p!=-1&&!ch[p][c];p=link[p])ch[p][c]=cur;
if(p==-1)link[cur]=0;
else{
int q=ch[p][c];
if(len[p]+1==len[q])link[cur]=q;
else{
int copy=++siz;
len[copy]=len[p]+1;
for(int i=0;i<26;i++)ch[copy][i]=ch[q][i];
for(;p!=-1&&ch[p][c]==q;p=link[p])ch[p][c]=copy;
link[copy]=link[q];
link[cur]=link[q]=copy;
}
}
last=cur;
}
void print(){//打印错误
cout<<"len"<<endl;
for(int i=0;i<=siz;i++)cout<<len[i]<<" \n"[i==siz];
cout<<"ch"<<endl;
for(int i=0;i<=siz;i++){
for(int j=0;j<26;j++){
if(ch[i][j])cout<<i<<" - "<<(char)('a'+j)<<" - "<<ch[i][j]<<endl;
}
}
cout<<"link"<<endl;
for(int i=0;i<=siz;i++)cout<<link[i]<<" \n"[i==siz];
}
/********** end **********/
int cnt[maxn<<1];//状态出现次数
vector<int> id[maxn];//长度为i的状态编号
void solve(){
//cin
string s;cin>>s;
//构造sam
init();
for(int i=0;i<s.size();i++)extend(s[i]-'a');
//将状态按长度分类
//性质1:s长度为i的前缀状态恰好为id[i][0]
//性质2:按长度跑 状态转移ch,后缀链接link 恰好符合一种拓扑序
for(int i=0;i<=siz;i++)id[len[i]].push_back(i);//len_id
//出现次数 按反向拓扑序跑
int LENMAX=s.size();//字符串长度
for(int i=LENMAX;i>=1;i--){//cnt
cnt[id[i][0]]++;//终止状态次数出现次数加一
for(auto x:id[i]){
cnt[link[x]]+=cnt[x];
}
}
//计算结果
long long ans=0;
for(int i=0;i<=siz;i++)if(cnt[i]>1)ans=max(ans,1ll*cnt[i]*len[i]);
cout<<ans<<endl;
}
}sam;
int main(){
sam.solve();
}
多项式
多项式乘法(FFT)
P3803 【模板】多项式乘法(FFT)
/*
[模板] 多项式乘法(FFT):
给定一个 n 次多项式 F(x),和一个 m 次多项式 G(x)。
请求出 F(x) 和 G(x) 的卷积。
复杂度 nlogn
*/
#include<bits/stdc++.h>
using namespace std;
typedef complex<double> cd;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
return x;
}
void wr(int a){
if(a<0)putchar('-'),a=-a;
if(a<=9)putchar(a|'0');
else{wr(a/10),putchar((a%10)|'0');}
}
void fft(vector<cd> &a,bool invert){
int n=a.size();
if(n==1)return;
vector<cd> a0(n/2),a1(n/2);
for(int i=0,j=0;i<n;i+=2,++j)a0[j]=a[i],a1[j]=a[i+1];
fft(a0,invert);
fft(a1,invert);
double ang=2*M_PI/n*(invert?-1:1);
cd w(1),wn(cos(ang),sin(ang));
for(int i=0;i<n/2;++i){
a[i]=a0[i]+w*a1[i];
a[i+n/2]=a0[i]-w*a1[i];
if(invert)a[i]/=2,a[i+n/2]/=2;
w*=wn;
}
}
vector<int> multiply(vector<int> &a,vector<int> &b){
vector<cd> fa(a.begin(),a.end()),fb(b.begin(),b.end());
int n=1;while(n<max(a.size(),b.size()))n<<=1;n<<=1;
fa.resize(n),fb.resize(n);
fft(fa,false),fft(fb,false);
for(int i=0;i<n;i++)fa[i]*=fb[i];
fft(fa,true);
vector<int> res(n);
for(int i=0;i<n;++i)res[i]=round(fa[i].real());
return res;
}
signed main(){
int n=read(),m=read();
vector<int> a(n+1);
vector<int> b(m+1);
for(int i=0;i<=n;i++)a[i]=read();
for(int i=0;i<=m;i++)b[i]=read();
vector<int> c=multiply(a,b);
for(int i=0;i<=n+m;i++)wr(c[i]),putchar(' ');
return 0;
}