0、目录
ac自动机、后缀数组、Trie树、kmp、回文串算法、后缀自动机、字符串哈希
1、ac自动机
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1000+10;
const int maxm=50+10;
char str[maxn][maxm],s[2000000+10];
int N,num[maxn];
struct AC{
#define sigma_size 26
#define maxnode 50000+10
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
void init(){ sz=1; memset(ch[0],0,sizeof(ch[0])); }
int idx(char c){ return c-'A'; }
void insert(char *s,int v){
int u=0,n=strlen(s);
for(int i=0;i<n;i++){
int c=idx(s[i]);
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
int f[maxnode],last[maxnode];
int getFail(){
queue<int> q;
f[0]=0;
for(int c=0;c<sigma_size;c++){
int u=ch[0][c];
if(u){ f[u]=0; q.push(u); last[u]=0; }
}
while(!q.empty()){
int r=q.front(); q.pop();
for(int c=0;c<sigma_size;c++){
int u=ch[r][c];
if(!u) continue;
q.push(u);
int v=f[r];
while(v&&!ch[v][c]) v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
void print(int j){
while(j){
num[val[j]]++;
j=last[j];
}
}
void find(char *T){
int n=strlen(T);
int j=0;
for(int i=0;i<n;i++){
int c=idx(T[i]);
if(c<0||c>=26){ j=0; continue; };
while(j&&!ch[j][c]) j=f[j];
j=ch[j][c];
if(val[j]) print(j);
else if(last[j]) print(last[j]);
}
}
}ac;
void init(){
memset(num,0,sizeof(num));
ac.init();
}
int main(){
while(cin>>N){
init();
for(int i=1;i<=N;i++){
scanf("%s",str[i]);
ac.insert(str[i],i);
}
ac.getFail();
scanf("%s",s);
ac.find(s);
for(int i=1;i<=N;i++){
if(num[i]){
printf("%s: %d
",str[i],num[i]);
}
}
}
return 0;
}
2、后缀数组
struct SuffixArray{
char s[maxn];
int sa[maxn],t[maxn],t2[maxn],c[maxn];
int n,m;
void init(int n,int m){
this->n=n;
this->m=m;
}
void build_sa(){
int i,*x=t,*y=t2;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
// for(i=0;i<n;i++) y[p++]=(sa[i]-k+n)%n;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1; x[sa[0]]=0;
for(i=1;i<n;i++){
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
}
if(p>=n) break;
m=p;
}
}
int rank[maxn],height[maxn];
void getHeight(){
int i,j,k=0;
for(i=0;i<n;i++) rank[sa[i]]=i;
for(i=0;i<n;i++){
if(k) k--;
if(rank[i]-1<0) continue;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
void solve(){
build_sa();
getHeight();
}
}mysa;
char str[maxn];
int main() {
scanf("%s",&str);
int n=strlen(str);
mysa.init(n+1,256);//末尾要加一个特别小的符号!,这里直接用' '了
strcpy(mysa.s,str);
mysa.solve();
return 0;
}