ac自動機系列

2021-06-23 00:56:38 字數 3063 閱讀 8036

求長度不超過l的串中,包含一些單詞的串的個數

首先構造自動機,然後把每個包含了終結態的狀態都置為終結態,比如abc b,那麼ab,abc,b都是終結態,

然後構造矩陣a,ax就是長度為一時得到的結果a^n為長度為n結果

其中x=[0,1,.........0]第乙個表示終結狀態,第二個表示起始狀態,最後乙個表示為長度小於當前長度的終結態數量之和(終結態表示這個串包含了至少乙個單詞)

接著構造a

對自動機上任意乙個狀態轉移u->v如果u是終結態就不轉移,否則a[v][u]++,

然後就用矩陣快速冪來求解a^n

最後的答案就是a[0][1]+a[s][1]   ==== 因為只有x[1] =1其他=0,表示當前長度終結態數量+小於當前長度終結態數量 = 最後答案

#include#include#include#includeusing namespace std;

#define maxn 40

int child[maxn][26],fail[maxn],state[maxn],flag[maxn];

int cnt;

void init()

char word[maxn];

void add(int u,int i)

if(child[u][x]==0)child[u][x] = cnt++;

add(child[u][x],i+1);

}#define ll unsigned __int64

int queue[100];

void build()}}

}struct matrix

};matrix operator*(matrix a,matrix b)

return c;

}int main()

build();

int s = 1;

for(int i = 1;i < cnt; i++)

if(flag[i]==0)state[i]=s++;

else state[i] = 0;

matrix a;

a.init();

for(int i = 1;i < cnt; i++)

}a.res[0][0] = 26;

a.res[s][0] = 1;

a.res[s][s] = 1;

matrix ans;

ans.init();

ans.n = a.n = s+1;

for(int i = 0;i < 30;i++) ans.res[i][i] = 1;

while(l)

ll f = ans.res[s][1]+ans.res[0][1];

printf("%i64u\n",f);

}return 0;

}

求乙個串包含哪些字串,根據題目意思的話,就不用想太多了,不會有重疊情況的,

比如abc bc這種的。

解題:把字串建立ac自動機,是單詞的終結態就標記為該單詞的標號,

然後對於每個串走一遍自動機,如果這個標號沒有出現過就加入ans

由於ans的大小<3 就直接判定就行了

#include#include#include#include#include#includeusing namespace std;

#define maxn 100007

struct node;

node node[maxn];

int cnt;

int newnode()

vectorans;

char word[maxn];

int super,root;

void insert(int u,int p,int flag)

int l = word[p];

if(node[u].child[l] == -1)

insert(node[u].child[l],p+1,flag);

}int queue[maxn];

void build()

else }}

}void find()

if(ans.size() == 4)return ;

}}int main()

build();

scanf("%d",&n);

int total = 0;

for(int i = 1;i <= n;i++)

}printf("total: %d\n",total);

}return 0;

}

求乙個串包含幾個單詞,

解法:構建ac自動機是單詞結尾的標記一下

然後走ac自動機,走到乙個狀態訪問fail節點,如果mark!=-就加上mark,然後mark=-1

這樣經過的狀態就不會重複計算了,

#include#include#include#includeusing namespace std;

struct nodeword[600001];

int cnt;

node*newnode()

void insert(node*root,char*s)

int id = *s-'a';

if(root->ch[id] == 0) root->ch[id] = newnode();

insert(root->ch[id],s+1);

}node *super,*root;

void build(node*root)

}}int autofind(char *s)

p = rt;

while(p != root && p->mark != -1)

s++;

}return ans;

}char a[1000009];

int main()

build(root);

scanf("%s",a);

int ans = autofind(a);

printf("%d\n",ans);

}return 0;

}

AC自動機 建立nlogn個AC自動機

string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...

AC自動機及字尾自動機

ac自動機是一種基於trie樹的演算法,其本質和kmp上的處理很相似。trie樹結構 kmp轉移思路 ac自動機組要由三個部分組成 trie樹的建立 fail指標的匹配 對ac自動機的詢問 每次建立自動機會有一次初始化 ac自動機類 struct node node結構體 struct ac voi...

AC自動機演算法

ac自動機簡介 首先簡要介紹一下ac自動機 aho corasickautomation,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹trie和kmp...