ac自动机
解决的问题 :
在一个文本串中查找多个模式串.
模板
https://www.luogu.com.cn/problem/P3808
int n,ans;
char s[N];
bool vis[N];
int tr[N][26];
int endd[N];
struct Trie {
int sz;
Trie() {
sz=1;
memset(tr[0],0,sizeof(tr[0]));
memset(vis,0,sizeof(vis));
}
void insert(char *s) {
int u =0,n=strlen(s);
for(int i=0; i<n; i++) {
int c = s[i] - 'a';
if(!tr[u][c]) {
memset(tr[sz],0,sizeof(tr[sz]));
endd[sz] = 0;
tr[u][c]=sz++;
}
u = tr[u][c];
}
endd[u]++;
}
};
int last[N],f[N];
void print(int j) {
if(j && !vis[j]) {
ans += endd[j];
vis[j] = 1;
print(last[j]);
}
}
void build() {
queue<int>q;
f[0] = 0;
for(int i=0; i<26; i++) {
int u = tr[0][i];
if(u) {
f[u] =0,last[u]=0,q.push(u);
}
}
while(!q.empty()) {
int r=q.front();
q.pop();
for(int c=0; c<26; c++) {
int u = tr[r][c];
if(!u) {
tr[r][c] = tr[f[r]][c];
continue;
}
q.push(u);
int v =f[r];
while(v && !tr[v][c])v = f[v];
f[u] = tr[v][c];
last[u] = endd[f[u]]?f[u]:last[f[u]];
}
}
}
void find(char *s){
int n = strlen(s);
int j =0;
for(int i=0;i<n;i++){
int c = s[i] - 'a';
j = tr[j][c];
if(endd[j])print(j);
else if(last[j])print(last[j]);
}
}
void work() {
scanf("%d",&n);
Trie trie;
ans = 0;
for(int i=1;i<=n;i++){
scanf("%s",s);
trie.insert(s);
}
build();
scanf("%s",s);
find(s);
printf("%d\n",ans);
}
查找文章中最多的模块串
https://www.luogu.com.cn/problem/P3796
int n,ans;
char s[N][155];
bool vis[N];
int tr[N][26];
int endd[N];
int id[N];
int num[N];
struct Trie {
int sz;
Trie() {
sz=1;
memset(tr[0],0,sizeof(tr[0]));
memset(vis,0,sizeof(vis));
}
void insert(char *s,int fa) {
int u =0,n=strlen(s);
for(int i=0; i<n; i++) {
int c = s[i] - 'a';
if(!tr[u][c]) {
memset(tr[sz],0,sizeof(tr[sz]));
endd[sz] = 0;
tr[u][c]=sz++;
}
u = tr[u][c];
}
endd[u]++;
id[u] = fa; //u这个结点对应fa字符串
}
};
int last[N],f[N];
void print(int j) {
if(j && !vis[j]) {
ans += endd[j];
num[id[j]]++; //记录个数
// vis[j] = 1;
print(last[j]);
}
}
void build() {
queue<int>q;
f[0] = 0;
for(int i=0; i<26; i++) {
int u = tr[0][i];
if(u) {
f[u] =0,last[u]=0,q.push(u);
}
}
while(!q.empty()) {
int r=q.front();
q.pop();
for(int c=0; c<26; c++) {
int u = tr[r][c];
if(!u) {
tr[r][c] = tr[f[r]][c];
continue;
}
q.push(u);
int v =f[r];
while(v && !tr[v][c])v = f[v];
f[u] = tr[v][c];
last[u] = endd[f[u]]?f[u]:last[f[u]];
}
}
}
void find(char *s) {
int n = strlen(s);
int j =0;
for(int i=0; i<n; i++) {
int c = s[i] - 'a';
j = tr[j][c];
if(endd[j])print(j);
else if(last[j])print(last[j]);
}
}
void work() {
while(~scanf("%d",&n) && n) {
Trie trie;
for(int i=0; i<n; i++) {
scanf("%s",s[i]);
trie.insert(s[i],i);
num[i] = 0;
}
build();
scanf("%s",s[n]);
find(s[n]);
int maxn = 0;
for(int i=0; i<n; i++) {
if(num[i] > maxn){
maxn = num[i];
}
}
printf("%d\n",maxn);
for(int i=0;i<n;i++){
if(num[i] == maxn){
printf("%s\n",s[i]);
}
}
}
}