發現一種新的思路,以前從來沒有見過的,即ac自動機的fail樹。
這一題我們先考慮暴力,從root往y的最後乙個點走,如果走到了x的末點,ans++,如果通過fail指標走到了x的末點,ans++。
反過來考慮,從x的末點開始,如果當前點在y串或者通過反向的fail到了y串,ans++。
又發把fail反向之後得到的是一棵樹,那麼也就是要求在x末點的子樹裡有多少個y點,轉化為dfs序後用樹狀陣列維護即可。
#include
#include
#include
#include
#include
#include
#include
#define x first
#define y second
#define ll long long
#define mp make_pair
#define lowbit(x) (x&(-x))
#define debug(...) fprintf(stderr,__va_args__)
using
namespace
std;
const
int maxn=1e5+10;
char s[maxn];
int n;
int first[maxn],e=0,next[maxn],to[maxn],sum[maxn*3],ans[maxn];
void add(int a,int b)
void _add(int x,int d)
}int query(int x)
return res;
}struct acm
int idx(char c)
void insert(char* s)
else
u=son[u][x];
}else
if(s[i]=='p')
val[++k]=u;
else
if(s[i]=='b')
u=fa[u];}}
void getfail()
}while(!q.empty())}}
void add(int a,int b)
void buildtree()
while(!q.empty())
}memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
}void dfs(int u)
r[u]=++dfs_clock;
}void solve()
else
if(s[i]=='p')
}else}}
}ac;
int main()
ac.solve();
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
bzoj2434 Noi2011 阿狸的打字機
傳送門 description 阿狸喜歡收藏各種稀奇古怪的東西,最近他淘到一台老式的打字機。打字機上只有28個按鍵,分別印有26個小寫英文本母和 b p 兩個字母。經阿狸研究發現,這個打字機是這樣工作的 l 輸入小寫字母,打字機的乙個凹槽中會加入這個字母 這個字母加在凹槽的最後 l 按一下印有 b ...
bzoj 2434 Noi2011 阿狸的打字機
time limit 10 sec memory limit 256 mb submit 3139 solved 1731 submit status discuss 阿狸喜歡收藏各種稀奇古怪的東西,最近他淘到一台老式的打字機。打字機上只有28個按鍵,分別印有26個小寫英文本母和 b p 兩個字母。...
BZOJ2434 NOI2011 阿狸的打字機
bzoj 洛谷我們先想一下最暴力是怎麼搞的 把 ac 自動機建好,每乙個節點,從 y 串的結尾節點往上跳它的父親,和普通的 ac 自動機一樣跳就好了 然而這個可以優化一下 我們將所有詢問離線 每個串統計一次其他串對它的貢獻 就可以有 70pts 了 70pts include include inc...