【模板】字符串

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;
}
posted @ 2020-11-12 13:42  MontesquieuE  阅读(28)  评论(0编辑  收藏  举报