【模板】字符串
Basic
Trie
//Author: RingweEH
//P2922 [USACO08DEC]Secret Message G
const int N=5e5+10;
struct Node{ int ch[2],tag,ed; }tr[N];
int n,m,len,a[N],tot=1;
void Insert( int n )
{
int p=1;
for ( int i=1; i<=n; i++ )
{
if ( !tr[p].ch[a[i]] ) { tr[p].ch[a[i]]=++tot; tr[tot].tag=tr[tot].ed=0; }
p=tr[p].ch[a[i]]; tr[p].tag++;
}
tr[p].ed++;
}
void Query( int n )
{
int p=1,ans=0;
for ( int i=1; i<=n; i++ )
{
if ( !tr[p].ch[a[i]] ) { printf("%d\n",ans ); return; }
p=tr[p].ch[a[i]]; ans+=tr[p].ed;
}
ans+=tr[p].tag-tr[p].ed; printf("%d\n",ans );
}
int main()
{
m=read(); n=read(); tr[1].tag=tr[1].ed=0;
for ( int i=1; i<=m; i++ )
{
len=read();
for ( int j=1; j<=len; j++ ) a[j]=read();
Insert(len);
}
for ( int i=1; i<=n; i++ )
{
len=read();
for ( int j=1; j<=len; j++ ) a[j]=read();
Query(len);
}
return 0;
}
KMP
//P3375 【模板】KMP字符串匹配
//Author: RingweEH
const int N=1e6+10;
int lena,lenb,nxt[N];
char sa[N],sb[N];
int main()
{
//freopen( "exam.in","r",stdin );
scanf( "%s%s",sa+1,sb+1 );
lena=strlen(sa+1); lenb=strlen(sb+1);
for ( int i=2,j=0; i<=lenb; i++ )
{
while ( j && sb[i]!=sb[j+1] ) j=nxt[j];
if ( sb[j+1]==sb[i] ) j++;
nxt[i]=j;
}
for ( int i=1,j=0; i<=lena; i++ )
{
while ( j && sb[j+1]!=sa[i] ) j=nxt[j];
if ( sb[j+1]==sa[i] ) j++;
if ( j==lenb ) { printf("%d\n",i-lenb+1 ); j=nxt[j]; }
}
for ( int i=1; i<=lenb; i++ ) printf("%d ",nxt[i] );
return 0;
}
AC自动机
//P3808 【模板】AC自动机(简单版)
//Author: RingweEH
const int N=2e6+10;
int n,tot,tr[N][26],fail[N],cnt[N];
char s[N];
void Insert( char *s )
{
int p=0,l=strlen(s);
for ( int i=0; i<l; i++ )
{
int ch=s[i]-'a';
if ( !tr[p][ch] ) tr[p][ch]=++tot;
p=tr[p][ch];
}
cnt[p]++;
}
void GetFail()
{
queue<int> q; fail[0]=0;
for ( int i=0; i<26; i++ )
if ( tr[0][i] ) fail[tr[0][i]]=0,q.push(tr[0][i]);
while ( !q.empty() )
{
int nw=q.front(); q.pop();
for ( int i=0; i<26; i++ )
if ( tr[nw][i] )
fail[tr[nw][i]]=tr[fail[nw]][i],q.push(tr[nw][i]);
else tr[nw][i]=tr[fail[nw]][i];
}
}
int Query( char *s )
{
int p=0,res=0,l=strlen(s);
for ( int i=0; i<l; i++ )
{
p=tr[p][s[i]-'a'];
for ( int j=p; j && cnt[j]!=-1; j=fail[j] ) res+=cnt[j],cnt[j]=-1;
}
return res;
}
int main()
{
//freopen( "exam.in","r",stdin );
scanf( "%d",&n );
for ( int i=1; i<=n; i++ ) scanf( "%s",s ),Insert(s);
GetFail(); scanf("%s",s);
printf("%d\n",Query(s) );
return 0;
}
Manacher
//Author:RingweEH
//P3805
const int N=2.2e7+10;
int len,pos[N];
char s[N],str[N];
void Init()
{
len=strlen(s); str[0]='@'; str[1]='#'; int j=2;
for ( int i=0; i<len; i++ ) str[j++]=s[i],str[j++]='#';
str[j]='\0'; len=j;
}
int main()
{
//freopen( "exam.in","r",stdin );
scanf("%s",s); Init();
int ans=-1,mx=0,id=0;
for ( int i=1; i<len; i++ )
{
if ( i<mx ) pos[i]=min(pos[id*2-i],mx-i);
else pos[i]=1;
while ( str[i+pos[i]]==str[i-pos[i]] ) pos[i]++;
if ( pos[i]+i>mx ) mx=pos[i]+i,id=i;
ans=max(ans,pos[i]-1);
}
printf("%d\n",ans );
return 0;
}
最小表示法
//UVA719 Glass Beads
//【模板】最小表示法
const int N=3e4+10;
int n,len;
char str[N];
int main()
{
//freopen( "exam.in","r",stdin );
int T; scanf("%d",&T);
while ( T-- )
{
scanf("%s",str); len=strlen(str);
int k=0,i=0,j=1;
while ( k<len && i<len && j<len )
{
int tmp=str[(i+k)%len]-str[(j+k)%len];
if ( tmp==0 ) k++;
else
{
if ( tmp<0 ) j+=k+1;
if ( tmp>0 ) i+=k+1;
if ( i==j ) i++;
k=0;
}
}
printf("%d\n",min(i,j)+1 );
}
return 0;
}
SAM
SAM
//Author:RingweEH
//P3804
const int N=1e6+1,M=26;
int n;
struct Suffix_Automaton
{
int len[N<<1],tr[N<<1][M],fa[N<<1],siz[N<<1],las=1,cnt=1;
void Insert( int c )
{
n++; int p=las,q=las=++cnt; len[q]=len[p]+1; siz[q]=1;
for ( ; p && !tr[p][c]; p=fa[p] )
tr[p][c]=q;
if ( !p ) { fa[q]=1; return; }
int np=tr[p][c];
if ( len[np]==len[p]+1 ) { fa[q]=np; return; }
int nq=++cnt; memcpy( tr[nq],tr[np],sizeof(tr[nq]) );
fa[nq]=fa[np]; fa[np]=fa[q]=nq;
len[nq]=len[p]+1;
for ( ; p && tr[p][c]==np; p=fa[p] )
tr[p][c]=nq;
}
int buc[N],ord[N<<1];
ll Query()
{
ll ans=0;
for ( int i=1; i<=cnt; i++ ) buc[len[i]]++;
for ( int i=1; i<=n; i++ ) buc[i]+=buc[i-1];
for ( int i=1; i<=cnt; i++ ) ord[buc[len[i]]--]=i;
for ( int i=cnt; i; i-- )
{
int p=ord[i]; siz[fa[p]]+=siz[p];
if ( siz[p]>1 ) ans=max( ans,1ll*siz[p]*len[p] );
}
return ans;
}
}sam;
int main()
{
char ch=getchar();
while ( ch>='a' && ch<='z' ) sam.Insert(ch-'a'),ch=getchar();
printf( "%lld\n",sam.Query() );
return 0;
}
广义SAM(离线BFS构造)
//Author:RingweEH
const int N=1e6+1,C=26;
int n;
char s[N];
struct Trie_Tree
{
int tot=1,c[N],fa[N],tr[N][C];
void Insert( char s[] )
{
int p=1,ch;
for ( int i=1; s[i]; i++ )
{
ch=s[i]-'a';
if ( !tr[p][ch] ) tr[p][ch]=++tot,fa[tot]=p,c[tot]=ch;
p=tr[p][ch];
}
}
}Trie;
struct Suffix_Automaton
{
int len[N<<1],tr[N<<1][C],fa[N<<1],cnt=1,pos[N<<1];
queue<int> que;
int Insert( int c,int las )
{
int p=las,q=++cnt; len[q]=len[p]+1;
for ( ; p && !tr[p][c]; p=fa[p] )
tr[p][c]=q;
if ( !p ) fa[q]=1;
else
{
int np=tr[p][c];
if ( len[np]==len[p]+1 ) fa[q]=np;
else
{
int nq=++cnt; memcpy( tr[nq],tr[np],sizeof(tr[nq]) );
fa[nq]=fa[np]; fa[np]=fa[q]=nq;
len[nq]=len[p]+1;
for ( ; p && tr[p][c]==np; p=fa[p] )
tr[p][c]=nq;
}
}
return q;
}
void Build()
{
for ( int i=0; i<C; i++ ) //插入第一层字符
if ( Trie.tr[1][i] ) que.push( Trie.tr[1][i] );
pos[1]=1; //Trie的根1在SAM上的位置为1
while ( !que.empty() )
{
int u=que.front(); que.pop();
pos[u]=Insert( Trie.c[u],pos[Trie.fa[u]] ); //一个是插入字符,一个是las
for ( int i=0; i<C; i++ )
if ( Trie.tr[u][i] ) que.push( Trie.tr[u][i] );
}
}
ll Query()
{
ll ans=0;
for ( int i=2; i<=cnt; i++ )
ans+=len[i]-len[fa[i]];
return ans;
}
}sam;
int main()
{
n=read();
for ( int i=1; i<=n; i++ )
scanf( "%s",s+1 ),Trie.Insert(s);
sam.Build();
printf( "%lld\n",sam.Query() );
return 0;
}
广义SAM(在线)
//Author:RingweEH
const int N=1e6+1,C=26;
int n;
struct Suffix_Automaton
{
int len[N<<1],tr[N<<1][C],fa[N<<1],cnt=1;
int Insert( int c,int las )
{
if ( tr[las][c] )
{
int p=las,np=tr[p][c];
if ( len[p]+1==len[np] ) return np;
else
{
int nq=++cnt; len[nq]=len[p]+1;
memcpy( tr[nq],tr[np],sizeof(tr[np]) );
fa[nq]=fa[np]; fa[np]=nq;
for ( ; p && tr[p][c]==np; p=fa[p] ) tr[p][c]=nq;
return nq;
}
}
int p=las,q=++cnt; len[q]=len[p]+1;
for ( ; p && !tr[p][c]; p=fa[p] )
tr[p][c]=q;
if ( !p ) fa[q]=1;
else
{
int np=tr[p][c];
if ( len[np]==len[p]+1 ) fa[q]=np;
else
{
int nq=++cnt; memcpy( tr[nq],tr[np],sizeof(tr[nq]) );
fa[nq]=fa[np]; fa[np]=fa[q]=nq;
len[nq]=len[p]+1;
for ( ; p && tr[p][c]==np; p=fa[p] )
tr[p][c]=nq;
}
}
return q;
}
ll Query()
{
ll ans=0;
for ( int i=2; i<=cnt; i++ )
ans+=len[i]-len[fa[i]];
return ans;
}
}sam;
int main()
{
n=read(); int las; char ch=' ';
for ( int i=1; i<=n; i++ )
{
las=1;
while ( ch<'a' || ch>'z' ) ch=getchar();
while ( ch>='a' && ch<='z' ) las=sam.Insert(ch-'a',las),ch=getchar();
}
printf( "%lld\n",sam.Query() );
return 0;
}
大地也该是从一片类似的光明中冒出来的。