P3966 [TJOI2013]单词(AC自动机)
生活随笔
收集整理的這篇文章主要介紹了
P3966 [TJOI2013]单词(AC自动机)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
裸題做法
按照題意把每個字符串拼接建立ACACAC自動機
然后在自動機上建立tiretiretire圖進行樹型dpdpdp
輸出就行了…
但是有問題
因為文章不是直接把字符串拼接出來的,兩個單詞間是有空隙的
所以我們也在拼接中的間隙加一個無法匹配的字符就好了,這樣就是模板題
#include <bits/stdc++.h> using namespace std; const int maxn = 2e6+10; int zi[maxn][27],fail[maxn],last[maxn],n,id,top,siz[maxn],mp[maxn]; char a[maxn]; string s[maxn]; struct edge{int to,nxt; }d[maxn]; int head[maxn],cnt=1; void add(int u,int v){ d[++cnt] = (edge){v,head[u]},head[u] = cnt; } void insert(string a,int index ) {int n = a.length(), now = 0;for(int i=0;i<n;i++){if( zi[now][a[i]-'a']==0 ) zi[now][a[i]-'a'] = ++id;now = zi[now][a[i]-'a'];}mp[index] = now; } void get_fail() {queue<int>q;for(int i=0;i<=26;i++)if( zi[0][i] ) q.push( zi[0][i] );while( !q.empty() ){int u = q.front(); q.pop();for(int i=0;i<=26;i++){if( zi[u][i] )fail[zi[u][i]] = zi[fail[u]][i],q.push( zi[u][i] );elsezi[u][i] = zi[fail[u]][i]; }} } void get_query() {int now = 0;for(int i=1;i<=top;i++){now = zi[now][a[i]-'a'];siz[now]++; } } void dfs(int u) {for(int i=head[u];i;i=d[i].nxt ){int v = d[i].to; dfs(v);siz[u] += siz[v];} } int main() {cin >> n;for(int i=1;i<=n;i++){cin >> s[i];insert( s[i],i );int len = s[i].length();for(int j=0;j<len;j++) a[++top] = s[i][j];a[++top] = 'a'+26;}get_fail(); get_query();for(int i=1;i<=id;i++) add(fail[i],i);dfs( 0 );for(int i=1;i<=n;i++) cout << siz[mp[i]] << endl; }稍變化的做法
建立acacac自動機
把單詞插入tiretiretire樹上的時候,把經過的路徑上的節點答案都加加
意思是根到這個點的單詞(如果有)答案就加加
當然這樣統計不完整,每個節點所有的后綴答案都應該加加
所以還是樹型dpdpdp寫…
總結
以上是生活随笔為你收集整理的P3966 [TJOI2013]单词(AC自动机)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: seo 搜索引擎优化, 网页中的meta
- 下一篇: 【原创】QT5-卸载精灵v1.0-卸载w