//ac自动机简单版板子(求有多少个不同的模式串在文本串里出现过)
struct tree
{
int fail; int vis[26]; int end;
}ac[N];
int cnt = 0;
void add(string s)//将模式串插入字典树
{
int l = s.length();
int now = 0;
for (int i = 0; i < l; i++)
{
if (ac[now].vis[s[i] - 'a'] == 0)
ac[now].vis[s[i] - 'a'] = ++cnt;
now = ac[now].vis[s[i] - 'a'];
}
ac[now].end += 1;
}
void get_fail()//得到fail数组
{
queue<int>q;
for (int i = 0; i < 26; i++)
{
if (ac[0].vis[i] != 0)
{
ac[ac[0].vis[i]].fail = 0;
q.push(ac[0].vis[i]);
}
}
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++)
{
if (ac[u].vis[i] != 0)
{
ac[ac[u].vis[i]].fail = ac[ac[u].fail].vis[i];
q.push(ac[u].vis[i]);
}
else
{
ac[u].vis[i] = ac[ac[u].fail].vis[i];
}
}
}
}
int ac_query(string s)
{
int l = s.length();
int now = 0, ans = 0;
for (int i = 0; i < l; i++)
{
now = ac[now].vis[s[i] - 'a'];
for (int j = now; j && ac[j].end != -1; j = ac[j].fail)
{
ans += ac[j].end;
ac[j].end = -1;
}
}
return ans;
}
int main()
{
int n = read();
string s;
for (int i = 1; i <= n; i++)
{
s = sread();
add(s);
}
ac[0].fail = 0;
get_fail();
s = sread();
cout << ac_query(s) << "\n";
return 0;
}
```
```
//哪些模式串在文本串中出现的次数最多
struct Tree//字典树
{
int fail;//失配指针
int vis[26];//子节点的位置
int end;//标记以这个节点结尾的单词编号
}AC[100000];//Trie树
int cnt = 0;//Trie的指针
struct Result
{
int num;
int pos;
}Ans[100000];//所有单词的出现次数
bool operator <(Result a, Result b)
{
if (a.num != b.num)
return a.num > b.num;
else
return a.pos < b.pos;
}
string s[100000];
inline void Clean(int x)
{
memset(AC[x].vis, 0, sizeof(AC[x].vis));
AC[x].fail = 0;
AC[x].end = 0;
}
inline void Build(string s, int Num)
{
int l = s.length();
int now = 0;//字典树的当前指针
for (int i = 0; i < l; ++i)//构造Trie树
{
if (AC[now].vis[s[i] - 'a'] == 0)//Trie树没有这个子节点
{
AC[now].vis[s[i] - 'a'] = ++cnt;//构造出来
Clean(cnt);
}
now = AC[now].vis[s[i] - 'a'];//向下构造
}
AC[now].end = Num;//标记单词结尾
}
void Get_fail()//构造fail指针
{
queue<int> Q;//队列
for (int i = 0; i < 26; ++i)//第二层的fail指针提前处理一下
{
if (AC[0].vis[i] != 0)
{
AC[AC[0].vis[i]].fail = 0;//指向根节点
Q.push(AC[0].vis[i]);//压入队列
}
}
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for (int i = 0; i < 26; ++i)
{
if (AC[u].vis[i] != 0)
{
AC[AC[u].vis[i]].fail = AC[AC[u].fail].vis[i];
Q.push(AC[u].vis[i]);
}
else
AC[u].vis[i] = AC[AC[u].fail].vis[i];
}
}
}
int AC_Query(string s)//AC自动机匹配
{
int l = s.length();
int now = 0, ans = 0;
for (int i = 0; i < l; ++i)
{
now = AC[now].vis[s[i] - 'a'];//向下一层
for (int t = now; t; t = AC[t].fail)//循环求解
Ans[AC[t].end].num++;
}
return ans;
}
int main()
{
int n;
while (233)
{
cin >> n;
if (n == 0)break;
cnt = 0;
Clean(0);
for (int i = 1; i <= n; ++i)
{
cin >> s[i];
Ans[i].num = 0;
Ans[i].pos = i;
Build(s[i], i);
}
AC[0].fail = 0;//结束标志
Get_fail();//求出失配指针
cin >> s[0];//文本串
AC_Query(s[0]);
sort(&Ans[1], &Ans[n + 1]);
cout << Ans[1].num << endl;
cout << s[Ans[1].pos] << endl;
for (int i = 2; i <= n; ++i)
{
if (Ans[i].num == Ans[i - 1].num)
cout << s[Ans[i].pos] << endl;
else
break;
}
}
return 0;
}
```
```
//(最终优化版)分别求出每个模式串Ti在S中出现的次数(拓扑优化版)
char s[N], T[N];
int n, cnt, vis[200051], ans, in[N], Map[N];
struct node
{
int son[26], fail, flag, ans;
void clear() { memset(son, 0, sizeof(son)), fail = flag = ans = 0; }
}trie[N];
queue<int>q;
void insert(char* s, int num)
{
int u = 1, len = strlen(s);
for (int i = 0; i < len; i++)
{
int v = s[i] - 'a';
if (!trie[u].son[v])trie[u].son[v] = ++cnt;
u = trie[u].son[v];
}
if (!trie[u].flag)trie[u].flag = num;
Map[num] = trie[u].flag;
}
void getFail()
{
for (int i = 0; i < 26; i++)trie[0].son[i] = 1;
q.push(1);
while (!q.empty())
{
int u = q.front(); q.pop();
int Fail = trie[u].fail;
for (int i = 0; i < 26; i++)
{
int v = trie[u].son[i];
if (!v) { trie[u].son[i] = trie[Fail].son[i]; continue; }
trie[v].fail = trie[Fail].son[i]; in[trie[v].fail]++;
q.push(v);
}
}
}
void topu()
{
for (int i = 1; i <= cnt; i++)
if (in[i] == 0)q.push(i);
while (!q.empty())
{
int u = q.front(); q.pop(); vis[trie[u].flag] = trie[u].ans;
int v = trie[u].fail; in[v]--;
trie[v].ans += trie[u].ans;
if (in[v] == 0)q.push(v);
}
}
void query(char* s)
{
int u = 1, len = strlen(s);
for (int i = 0; i < len; i++)
u = trie[u].son[s[i] - 'a'], trie[u].ans++;
}
int main()
{
scanf("%d", &n); cnt = 1;
for (int i = 1; i <= n; i++)
{
scanf("%s", s);
insert(s, i);
}
getFail(); scanf("%s", T);
query(T); topu();
for (int i = 1; i <= n; i++)printf("%d\n", vis[Map[i]]);
}
自用板子