HDU 2222 Keywords Search
- 题意:问文本串中出现了多少种模式串。
AC CODE【AC奥特曼板子题~】
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxS = 1000006;
const int maxN = 500005;
struct AC_automat{
int trie[maxN][26], tot;
int sum[maxN];
int fail[maxN];
void Clear(int rt)
{
for(int i = 0; i < 26; ++ i )
trie[rt][i] = 0;
sum[rt] = 0;
}
void init()
{
Clear(0);
tot = 0;
}
void Insert(char *s)
{
int rt = 0;
for(int i = 0; s[i]; ++ i)
{
int id = s[i] - 'a';
if(!trie[rt][id]) { trie[rt][id] = ++ tot; Clear(tot); }
rt = trie[rt][id];
}
++ sum[rt];
}
void build()
{
memset(fail, 0, sizeof(fail));
queue<int>q;
for(int i = 0; i < 26; ++ i) if(trie[0][i]) q.push(trie[0][i]);
while(!q.empty())
{
int rt = q.front(); q.pop();
for(int i = 0; i < 26; i ++ )
{
if(trie[rt][i])
{
fail[trie[rt][i]] = trie[fail[rt]][i];
q.push(trie[rt][i]);
} else trie[rt][i] = trie[fail[rt]][i];
}
}
}
int query(char *t)
{
int ans = 0;
int now = 0;
for(int i = 0; t[i]; ++ i )
{
int id = t[i] - 'a';
now = trie[now][id];
for(int nex = now; nex && ~sum[nex]; nex = fail[nex])
ans += sum[nex], sum[nex] = -1;
}
return ans;
}
}ac_auto;
int n; char s[maxS];
int main()
{
int TAT; scanf("%d", &TAT);
while(TAT -- )
{
ac_auto.init();
scanf("%d", &n);
for(int i = 0; i < n; ++ i )
{
scanf("%s", s);
ac_auto.Insert(s);
}
ac_auto.build();
scanf("%s", s);
printf("%d\n", ac_auto.query(s));
}
return 0;
}
Last优化代码~
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 500005;
const int maxS = 1000006;
struct AC_automat{
int trie[maxN][26], tot;
int sum[maxN];
int fail[maxN], last[maxN];
void Clear(int rt)
{
for(int i = 0; i < 26; ++ i )
trie[rt][i] = 0;
sum[rt] = 0;
}
void init()
{
Clear(0);
tot = 0;
}
void Insert(char *s)
{
int rt = 0;
for(int i = 0; s[i]; ++ i )
{
int id = s[i] - 'a';
if(!trie[rt][id]) { trie[rt][id] = ++ tot; Clear(tot); }
rt = trie[rt][id];
}
++ sum[rt];
}
void build()
{
queue<int>q;
fail[0] = last[0] = 0;
for(int i = 0; i < 26; ++ i) if(trie[0][i]) { last[trie[0][i]] = fail[trie[0][i]] = 0; q.push(trie[0][i]); }
while(!q.empty())
{
int rt = q.front(); q.pop();
for(int i = 0; i < 26; ++ i )
{
if(trie[rt][i])
{
fail[trie[rt][i]] = trie[fail[rt]][i];
q.push(trie[rt][i]);
int p = trie[rt][i];
last[p] = sum[fail[p]] ? fail[p] : last[fail[p]];
} else trie[rt][i] = trie[fail[rt]][i];
}
}
}
int query(char *t)
{
int ans = 0;
int rt = 0;
for(int i = 0; t[i]; ++ i )
{
rt = trie[rt][t[i] - 'a'];
int nex = sum[rt] ? rt : last[rt];
for( ; nex && ~sum[nex]; nex = last[nex])
ans += sum[nex], sum[nex] = -1;
}
return ans;
}
}AC;
int n;
char s[maxS];
int main()
{
int TAT; scanf("%d", &TAT);
while(TAT -- )
{
AC.init();
scanf("%d", &n);
for(int i = 0; i < n; ++ i )
{
scanf("%s", s);
AC.Insert(s);
}
AC.build();
scanf("%s", s);
printf("%d\n", AC.query(s));
}
return 0;
}
/*
10
5
she
he
say
shr
her
yasherhs
6
she
her
he
him
his
e
hisheher
*/