HDU 3065 病毒侵襲持續中
- 題意:給出n個全是英文大寫字母的模式串,保證每個模式串不完全相同。然後再給出一個文本串,字符集由包含ASCII可見字符組成。問每個模式串在文本串中出現的次數。
一:
- 思路:其實就是一個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 maxN = 50004;
const int maxS = 2000006;
char str[1005][55];
struct AC_automat{
int trie[maxN][26], tot;
int fail[maxN];
int endd[maxS];
int times[maxN];
void Clear(int rt)
{
for(int i = 0; i < 26; i ++ )
trie[rt][i] = 0;
times[rt] = 0;
}
void init()
{
tot = 0;
Clear(0);
}
void Insert(char *s, int p)
{
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];
}
endd[p] = rt;
}
void build()
{
memset(fail, 0, sizeof(fail));
queue<int>que;
for(int i = 0; i < 26; i ++ )
if(trie[0][i]) que.push(trie[0][i]);
while(!que.empty())
{
int rt = que.front(); que.pop();
for(int i = 0; i < 26; i ++ )
{
if(trie[rt][i])
{
fail[trie[rt][i]] = trie[fail[rt]][i];
que.push(trie[rt][i]);
} else trie[rt][i] = trie[fail[rt]][i];
}
}
}
void query(char *t)
{
int now = 0;
for(int i = 0; t[i]; i ++ )
{
if(t[i] >= 'A' && t[i] <= 'Z')
{
int id = t[i] - 'A';
now = trie[now][id];
for(int nex = now; nex ; nex = fail[nex])
++ times[nex];
} else now = 0;
}
}
void print(int n)
{
for(int i = 0; i < n; ++ i )
{
if(times[endd[i]])
printf("%s: %d\n", str[i], times[endd[i]]);
}
}
}ac_auto;
int n;
char s[maxS];
int main()
{
while(~scanf("%d", &n))
{
ac_auto.init();
for(int i = 0; i < n; i ++ )
{
scanf("%s", str[i]);
ac_auto.Insert(str[i], i);
}
ac_auto.build();
getchar();
gets(s);
ac_auto.query(s);
ac_auto.print(n);
}
return 0;
}
二:
思路:用Fail樹求解
這個和P5357 【模板】AC自動機(二次加強版)大致是一樣的,只是文本串的範圍大了些。我們遍歷的時候直接不管大寫字母之外的字符就可。
注意
可能包含空格,所以用gets讀入文本串【好叭是我想多了,空格好像不是ascii碼可見字符,scanf也可以的】- 初始化的問題。該題是多組輸入!!!洛谷是單組的,所以我構建fail樹的時候沒有對vector進行初始化,也沒關係。然後這道題就WA了,調了下發現是vector沒有清空TAT。
#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 = 2000006;
const int maxN = 50004 * 26;
char str[1003][55];
struct AC_automat{
int trie[maxN][26], tot;
int fail[maxN];
int times[maxN];
int endd[maxS];
void Clear(int rt)
{
for(int i = 0; i < 26; ++ i )
trie[rt][i] = 0;
times[rt] = 0;
}
void init()
{
tot = 0;
Clear(0);
}
void Insert(char *s, int pos)
{
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];
}
endd[pos] = 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];
}
}
}
void get_times(char *t)
{
int now = 0;
for(int i = 0; t[i]; ++ i)
{
if(t[i] >= 'A' && t[i] <= 'Z')
++ times[now = trie[now][t[i] - 'A']];
else
now = 0;
}
}
vector<int>vt[maxN];
void buildFail()
{
for(int i = 0; i <= tot; ++ i)
vt[i].clear();
for(int i = 1; i <= tot; ++ i)
vt[fail[i]].push_back(i);
}
void dfs(int u)
{
int siz = vt[u].size();
for(int i = 0; i < siz; ++ i )
{
int v = vt[u][i];
dfs(v);
times[u] += times[v];
}
}
void print(int n)
{
for(int i = 0; i < n; ++ i )
{
if(times[endd[i]])
printf("%s: %d\n", str[i], times[endd[i]]);
}
}
}ac;
int n;
char s[maxS];
int main()
{
while(~scanf("%d", &n))
{
ac.init();
for(int i = 0; i < n; ++ i )
{
scanf("%s", str[i]);
ac.Insert(str[i], i);
}
getchar();
ac.build();
gets(s);
ac.get_times(s);
ac.buildFail();
ac.dfs(0);
ac.print(n);
}
return 0;
}
/*
6
SHE
HER
HE
HIM
HIS
E
SHEHEHEHEHIMHEHERiii...eE
4
AA
AAA
BB
CC
ooxxCC%dAAAoen.. ..END
*/