AC自动机判母串中出现几次子串的个数(hdu2222)
#include<iostream>
#include<queue>
using namespace std ;
const int maxn = 500005 ;
const int Max = 26 ;
struct Trie
{
int next[maxn][Max];
int fail[maxn];
int sum[maxn];
int L,root;
int cnt;
int newnode()
{
for (int i = 0 ;i < Max;i++)
next[L][i] = -1 ;
sum[L] = 0 ;
fail[L] = -1 ;
return L++;
}
void init()
{
L = 0 ;
cnt = 0 ;
root = newnode();
}
void insert(char s[])
{
int len = strlen (s);
int p = root;
for (int i = 0 ;i < len;i++)
{
int to = s[i] - 'a' ;
if (next[p][to] == -1 )
{
next[p][to] = newnode();
}
p = next[p][to];
}
sum[p]++;
}
void build_fail()
{
int p = root;
queue <int > Q;
for (int i = 0 ;i < Max;i++)
{
if (next[p][i] != -1 )
{
fail[next[p][i]] = root;
Q.push(next[p][i]);
}
}
while (!Q.empty())
{
int u = Q.front();Q.pop();
for (int i = 0 ;i < Max;i++)
{
if (next[u][i]!=-1 )
{
p = fail[u];
while (p!=-1 )
{
if (next[p][i] != -1 )
{
fail[next[u][i]] = next[p][i];
break ;
}
p = fail[p];
}
if (fail[next[u][i]] == -1 )
fail[next[u][i]] = root;
Q.push(next[u][i]);
}
}
}
}
void ac_automation(char *ch)
{
int p = root;
int len = strlen (ch);
for (int i = 0 ;i < len;i++)
{
int x = ch[i] - 'a' ;
while (next[p][x] == -1 && p != root)p = fail[p];
p = next[p][x];
if (p == -1 )p = root;
int temp = p;
while (temp != root)
{
if (sum[temp] > 0 )
{
cnt += sum[temp];
sum[temp] = -1 ;
}
else break ;
temp = fail[temp];
}
}
}
}ac;
char check[1000006 ];
int main()
{
int T;
scanf ("%d" , &T);
while (T--)
{
ac.init();
int n;
cin >> n;
char s[55 ];
for (int i = 1 ;i <= n;i++)
{
scanf ("%s" , s);
ac.insert(s);
}
ac.build_fail();
scanf ("%s" , check);
ac.ac_automation(check);
cout << ac.cnt << endl;
}
}
利用fail指针来进行状态转移(2017香港区域赛J题)
#include<bits/stdc++.h>
using namespace std ;
const int maxn=200005 ;
const int MAX=2 ;
int G[maxn][2 ];
void add_edge(int u,int v,int w)
{
G[u][w]=v;
}
struct Trie
{
int next[maxn][MAX],fail[maxn];
bool end[maxn];
int L,root;
int newnode()
{
for (int i=0 ; i<MAX; i++)
next[L][i]=-1 ;
end[L]=0 ;
L++;
return L-1 ;
}
void init()
{
L=0 ;
root=newnode();
}
void insert(char str[],int len)
{
int p=root;
for (int i=0 ; i<len; i++)
{
int num=str[i]-'0' ;
if (next[p][num]==-1 )
{
next[p][num]=newnode();
}
p=next[p][num];
}
end[p]=1 ;
}
void build()
{
int p=root;
queue <int > Q;
for (int i=0 ; i<MAX; i++)
{
if (next[p][i]==-1 )
next[p][i]=root;
else
{
fail[next[p][i]]=root;
Q.push(next[p][i]);
}
}
while (!Q.empty())
{
int u=Q.front();
Q.pop();
if (end[fail[u]])end[u]=1 ;
for (int i=0 ; i<MAX; i++)
{
int &v=next[u][i];
if (v==-1 )
{
v=next[fail[u]][i];
}
else
{
Q.push(v);
fail[v]=next[fail[u]][i];
}
}
}
}
int in[maxn],in2[maxn];
int inq[maxn];
bool vis[maxn];
void dfs1(int u)
{
for (int i=0 ;i<MAX;i++)
{
int v=next[u][i];
if (end[v])continue ;
in[v]++;
in2[v]++;
if (in[v]==1 )
dfs1(v);
}
}
bool check()
{
memset (in,0 ,sizeof (in));
memset (inq,0 ,sizeof (inq));
memset (vis,0 ,sizeof (vis));
dfs1(0 );
queue <int > Q;
if (in[0 ])return 1 ;
Q.push(0 );
while (!Q.empty())
{
int u=Q.front();Q.pop();
for (int i=0 ;i<MAX;i++)
{
int v=next[u][i];if (end[v])continue ;
vis[v]=1 ;
in[v]--;
if (!in[v])
{
inq[v]=1 ;
Q.push(v);
}
}
}
for (int i=0 ;i<L;i++)
{
if (vis[i]!=inq[i])return 1 ;
}
return 0 ;
}
int dp[maxn];
int to[maxn];
int Max=0 ;
void dfs(int u)
{
for (int i=0 ;i<MAX;i++)
{
int v=next[u][i];
if (end[v])continue ;
dfs(v);
to[u]=max(to[u],to[v]+1 );
if (dp[u]+to[v]+1 ==Max)
{
add_edge(u,v,i);
}
}
}
void solve()
{
if (check())
{
printf ("-1" );
return ;
}
memset (dp,0 ,sizeof (dp));
memset (to,0 ,sizeof (to));
memset (G,-1 ,sizeof (G));
queue <int > Q;
Q.push(0 );
while (!Q.empty())
{
int u=Q.front();Q.pop();
for (int i=0 ;i<MAX;i++)
{
int v=next[u][i];
if (end[v])continue ;
in2[v]--;
if (dp[v]<dp[u]+1 )
dp[v]=dp[u]+1 ,Max=max(Max,dp[v]);
if (!in2[v])
Q.push(v);
}
}
dfs(0 );
int p=root;
while (dp[p]!=Max)
{
if (G[p][0 ]!=-1 )
{
printf ("0" );
p=G[p][0 ];
}
else
{
printf ("1" );
p=G[p][1 ];
}
}
}
} ac;
char num[200005 ];
int main()
{
int N;
cin >>N;
ac.init();
for (int i=1 ; i<=N; i++)
{
scanf ("%s" ,num);
ac.insert(num,strlen (num));
}
ac.build();
ac.solve();
return 0 ;
}