先安利一篇好文章(后缀数组:) https://xminh.github.io/oi/2018/02/27/%E5%90%8E%E7%BC%80%E6%95%B0%E7%BB%84-%E6%9C%80%E8%AF%A6%E7%BB%86(maybe)%E8%AE%B2%E8%A7%A3.html
字符串算法 最普适的无非hash 而博主学过hash及kmp 本篇不再呈现
AC自动机
懒死了。。。
#include<bits/stdc++.h>
#define N 500010
using namespace std;
queue<int>q;
struct Aho_Corasick_Automaton{
int c[N][26],val[N],fail[N],cnt;
void ins(char *s){
int len=strlen(s);int now=0;
for(int i=0;i<len;i++){
int v=s[i]-'a';
if(!c[now][v])c[now][v]=++cnt;
now=c[now][v];
}
val[now]++;
}
void build(){
for(int i=0;i<26;i++)if(c[0][i])fail[c[0][i]]=0,q.push(c[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++)
if(c[u][i])fail[c[u][i]]=c[fail[u]][i],q.push(c[u][i]);
else c[u][i]=c[fail[u]][i];
}
}
int query(char *s){
int len=strlen(s);int now=0,ans=0;
for(int i=0;i<len;i++){
now=c[now][s[i]-'a'];
//for(int t=now;t&&~val[t];t=fail[t])ans+=val[t],val[t]=-1;
int temp=now;
while(temp)
{
ans+=val[temp];
val[temp]=0;
temp=fail[temp];
}
}
return ans;
}
}AC;
int n;char p[1000005];
int main(){
//freopen("automaton.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%s",p),AC.ins(p);
AC.build();
scanf("%s",p);int ans=AC.query(p);
printf("%d",ans);
return 0;
}
给我一个教训——网上代码别随便学,很有可能常数极大(而且不能AC模板题!)
后缀数组
#include<bits/stdc++.h>
using namespace std;
#define MN 1000020
#define so(i,j,k,l) for(int i=j;i<=k;i+=l)
#define si(i,j,k,l) for(int i=j;i>=k;i-=l)
int c[MN],height[MN],rk[MN],sa[MN],x[MN],y[MN];
char s[MN];int n,m;
void mk_sa()
{
so(i,1,n,1) c[x[i]=s[i]]++;
so(i,1,m,1) c[i]+=c[i-1];
si(i,n,1,1) sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int tot=0;
so(i,n-k+1,n,1) y[++tot]=i;
so(i,1,n,1)
if(sa[i]>k) y[++tot]=sa[i]-k;
so(i,1,m,1) c[i]=0;
so(i,1,n,1) c[x[i]]++;
so(i,2,m,1) c[i]+=c[i-1];
si(i,n,1,1) sa[c[x[y[i]]]--]=y[i],y[i]=0;
swap(x,y);
x[sa[1]]=1;tot=1;
so(i,2,n,1)
x[sa[i]]=
(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?tot:++tot;
if(tot==n) break;
m=tot;
}
so(i,1,n,1) printf("%d ",sa[i]);
}
void mk_height()
{
int k=0;
so(i,1,n,1) rk[sa[i]]=i;
so(i,1,n,1)
{
if(rk[i]==1) continue;
if(k) --k;
int j=sa[rk[i]-1];
while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k]) k++;
height[rk[i]]=k;
}
}
int main()
{
scanf("%s",s+1);n=strlen(s+1);m=(int)'z';
//for(int i=1;i<=n;i++) cout<<s[i];
//cout<<n;
mk_sa();
//mk_height();
return 0;
}
为什么勤劳的LittlePrincess这篇偷懒了呢?
他还没写语文作文!!!!!!!!!!!