A string S of N chars is given
We were asked to use m strings to match . Each string can be used serval times .strings for matching can intersect with each other .
The question is to find out how many chars of S can’t be matched .
The solution is AC_AUTOMAN .
this is the first time I type this algorithm .
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std ;
#define N 300010
#define M 5100
char s[N] , z[M] ;
int i , j , k , n , m , T ;
int q[4000010] ;
struct AC_Automan {
AC_Automan() {
Len = -1 ;
}
int s[27] , nx , Len , de ;
bool En ;
}g[4000010] ;
int tag[N] ;
int main() {
scanf("%d%s%d",&n,s,&m ) ;
for( i=1 ; i<=m ; i++ ) {
scanf("%s",z ) ;
int l = strlen( z ) ;
int x = 0 ;
for( j=0 ; j<l ; j++ ) {
if( g[x].s[ z[j]-'a' ]==0 )
g[x].s[ z[j]-'a' ] = ++ T ;
x = g[x].s[ z[j]-'a' ] ;
}
g[x].En = 1 ;
}
int l = 0 , r = 0 ;
for( i=0 ; i<26 ; i++ ) if( g[0].s[i] ) q[++r] = g[0].s[i] ;
while( l!=r ) {
int x = q[++l] ;
for( i=0 ; i<26 ; i++ ) if( g[x].s[i] ) {
int tmp = q[++r] = g[x].s[i] ;
g[tmp].nx = g[ g[x].nx ].s[i] ;
g[tmp].de = g[x].de + 1 ;
} else g[x].s[i] = g[ g[x].nx ].s[i] ;
if( g[x].En ) g[x].Len = g[x].de ;
if( g[x].Len<0 ) g[x].Len = g[ g[x].nx ].Len ;
}
int x = 0 ;
for( i=0 ; i<n ; i++ ) {
x = g[x].s[ s[i]-'a' ] ;
if( g[x].Len>=0 ) tag[ i-g[x].Len ] ++ , tag[i+1] -- ;
}
int ans = 0 , cover = 0 ;
for( i=0 ; i<n ; i++ ) cover += tag[i] , ans += ( cover == 0 ) ;
printf("%d\n",ans ) ;
}
Here are some tips :
the void root ‘d better be zero for convenience .
the fail pointer tips ::
“`
for( i=0 ; i<26 ; i++ ) if( g[x].s[i] ) {
int tmp = q[++r] = g[x].s[i] ;
g[tmp].nx = g[ g[x].nx ].s[i] ;
g[tmp].de = g[x].de + 1 ;
} else g[x].s[i] = g[ g[x].nx ].s[i] ;
if( g[x].En ) g[x].Len = g[x].de ;
if( g[x].Len<0 ) g[x].Len = g[ g[x].nx ].Len ;
“`
this is the whole procedure of bfs , I think this is the main part of AC_AM .
That told the construction of failure pointer .