求長度不超過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...