字符串
kmp
char s[maxn],q[maxn];
int n,m,nxt[maxn];
int main(){
scanf("%s%s",s+1,q+1);n=strlen(s+1),m=strlen(q+1);
for(int i=2,j=0;i<=m;i++){
while(j&&q[i]!=q[j+1])j=nxt[j];
if(q[i]==q[j+1])j++;
nxt[i]=j;
}
for(int i=1,j=0;i<=n;i++){
while(j&&s[i]!=q[j+1])j=nxt[j];
if(s[i]==q[j+1])j++;
if(j==m){
printf("%d\n",i-m+1);
j=nxt[j];
}
}
for(int i=1;i<=m;i++)printf("%d ",nxt[i]);
}
manacher
int n,ans;
char s[maxn],a[maxn<<1];
int len[maxn<<1];
void change(){
a[0]='#';a[1]='#';
for(int i=1;i<=n;i++)a[i<<1]=s[i],a[i<<1|1]='#';
n=n<<1|1;
}
void manacher(){
int maxr=0,mid=0;
for(int i=1;i<=n;i++){
if(i<maxr)len[i]=min(len[mid*2-i],len[mid]+mid-i);
else len[i]=1;
while(a[i+len[i]]==a[i-len[i]])++len[i];
if(len[i]+i>maxr){
maxr=len[i]+i;
mid=i;
}
}
}
signed main(){
scanf("%s",s+1);n=strlen(s+1);
change();manacher();
for(int i=1;i<=n;i++)ans=max(ans,len[i]);
printf("%d",ans-1);
}
Z 函数
int n,z[maxn];
char s[maxn];
void work(){
scanf("%s",s);n=strlen(s);
for(int i=1,l=0,r=0;i<n;i++){
z[i]=max(0ll,min(z[i-l],r-i+1));
while(i+z[i]<n&&s[z[i]]==s[i+z[i]])z[i]++;
if(i+z[i]-1>r)l=i,r=i+z[i]-1;
}
for(int i=0;i<n;i++)printf("%lld ",z[i]);
}
SAM
int n,ans;
char s[maxn];
int len[maxn],lnk[maxn];
int a[maxn][26];
int p=1,cur=1;
int siz[maxn];
void insert(int c){
int nd=++cur;
len[nd]=len[p]+1;siz[nd]=1;
while(p&&!a[p][c])a[p][c]=nd,p=lnk[p];
if(!p){lnk[p=nd]=1;return ;}
int q=a[p][c];
if(len[p]+1==len[q])lnk[nd]=q;
else{
int cl=++cur;
len[cl]=len[p]+1,lnk[cl]=lnk[q];
memcpy(a[cl],a[q],sizeof(a[q]));
lnk[nd]=lnk[q]=cl;
while(p&&a[p][c]==q)a[p][c]=cl,p=lnk[p];
}
p=nd;
}
int head[maxn],tot;
struct nd{
int nxt,to;
}e[maxn];
void add(int u,int v){e[++tot]={head[u],v};head[u]=tot;}
void dfs(int u){
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
dfs(v),siz[u]+=siz[v];
}
}
void work(){
scanf("%s",s+1),n=strlen(s+1);
for(int i=1;i<=n;i++)insert(s[i]-'a');
for(int i=2;i<=cur;i++)add(lnk[i],i);
dfs(1);
for(int i=2;i<=cur;i++)if(siz[i]>1)ans=max(ans,siz[i]*len[i]);
printf("%lld\n",ans);
}
带通配符字符串匹配
ntt 部分略。要求 不能过大,否则使用 fft。
int n,m;
char s[maxn],t[maxn];
int f[maxn],g[maxn],res[maxn];
vector<int> ans;
void work(){
m=read();n=read();
scanf("%s%s",t,s);
reverse(t,t+m);
int lim=1;while(lim<n)lim<<=1;
for(int i=0;i<lim;i++)to[i]=(to[i>>1]>>1)|((i&1)?lim>>1:0);
for(int i=0;i<m;i++)if(t[i]!='*')f[i]=(t[i]-'a')*(t[i]-'a');
for(int i=0;i<n;i++)if(s[i]!='*')g[i]=1;
ntt(f,lim,1),ntt(g,lim,1);
for(int i=0;i<lim;i++)res[i]=f[i]*g[i]%mod,f[i]=g[i]=0;
for(int i=0;i<m;i++)if(t[i]!='*')f[i]=t[i]-'a';
for(int i=0;i<n;i++)if(s[i]!='*')g[i]=s[i]-'a';
ntt(f,lim,1),ntt(g,lim,1);
for(int i=0;i<lim;i++)(res[i]+=mod-2*f[i]*g[i]%mod)%=mod,f[i]=g[i]=0;
for(int i=0;i<m;i++)if(t[i]!='*')f[i]=1;
for(int i=0;i<n;i++)if(s[i]!='*')g[i]=(s[i]-'a')*(s[i]-'a');
ntt(f,lim,1),ntt(g,lim,1);
for(int i=0;i<lim;i++)(res[i]+=f[i]*g[i])%=mod,f[i]=g[i]=0;
ntt(res,lim,-1);
for(int i=m-1;i<n;i++)if(!res[i])ans.pb(i-m+2);
printf("%lld\n",(int)ans.size());
for(int i:ans)printf("%lld ",i);
}