阿狸喜歡收藏各種稀奇古怪的東西,最近他淘到一台老式的打字機。打字機上只有28個按鍵,分別印有 26個小寫英文本母和』b』、』p』兩個字母。 經阿狸研究發現,這個打字機是這樣工作的:
輸入小寫字母,打字機的乙個凹槽中會加入這個字母(按 p 前凹槽中至少有乙個字母)。
按一下印有』b』的按鍵,打字機凹槽中最後乙個字母會消失。
按一下印有』p』的按鍵,打字機會在紙上列印出凹槽中現有的所有字母並換行,但凹槽中的字母不會消失(保證凹槽中至少有乙個字母) 。
例如,阿狸輸入 apapbbp,紙上被列印的字元如下:
a aa
ab 我們把紙上列印出來的字串從 1開始順序編號,一直到 n。打字機有乙個非常有趣的功能,在打字機中暗藏乙個帶數字的小鍵盤,在小鍵盤上輸入兩個數(x,y)(其中1≤x,y≤n),打字機會顯示第x個列印的字串在第y個列印的字串中出現了多少次。 阿狸發現了這個功能以後很興奮,他想寫個程式完成同樣的功能,你能幫助他麼?
比較幾個匹配串,一般來說ac自動機是乙個很好的選擇。
根據輸入的第乙個長字串,考慮p和b表示什麼。
建造trie的時候,p表示標記,b表示回到自己的父親,小寫字母表示向下走。
但是有這麼多組詢問,怎麼用很短的時間解決掉他們呢?
題目條件:
①被列印的字串是有序的,即trie上的乙個節點表示被列印的字串的乙個區間[l,r]。
②問乙個串在另乙個串中出現了幾次。
相應對策:
那麼再跑一遍trie,就可以解決掉[l,r]區間的問題。
只需要在進來這個點時在資料結構中+1,出去時-1即可。
問次數,就是問在fail樹上,根節點到某個其子樹種節點的路徑上,有幾個+1。
#include
#include
#include
#include
#include
#include
#define n 100010
#define p(a) putchar(a)
#define fo(i,a,b) for(i=a;i<=b;i++)
using
namespace
std;
struct note;note qu[n];
struct note1;note1 edge[n];
int tot,head[n],ans[n];
int i,j,k,l,n,m,x,gs,cs,wz,y;
int c[n],u,v;
int tr[n][26],fail[n],bz[n],pre[n];
int dfn[n],t,fa[n];
int val[n],siz[n];
char s[n],ch;
queue
q;int read()
void write(int x)
void lb(int x,int y)
int lowbit(int x)
void ins(int x,int delta)
int query(int x)
void dfs(int x)
}bool cmp(note x,note y)
k=0;gs=0;pre[0]=-1;
fo(i,1,l)
} else
if(ch=='b')k=pre[k];else bz[++cs]=k;
}fail[0]=-1;
q.push(0);
while(!q.empty())
}fo(i,1,gs)lb(fail[i],i);
dfs(0);
sort(qu+1,qu+n+1,cmp);
k=0;y=1;
ins(1,1);
fo(i,1,l) else
if(ch=='b')
else}}
ins(1,-1);
fo(i,1,n)write(ans[i]),p('\n');
return
0;}
NOI2011阿狸的打字機
阿狸喜歡收藏各種稀奇古怪的東西,最近他淘到一台老式的打字機。打字機上只有28個按鍵,分別印有26個小寫英文本母和 b p 兩個字母。經阿狸研究發現,這個打字機是這樣工作的 l 輸入小寫字母,打字機的乙個凹槽中會加入這個字母 這個字母加在凹槽的最後 l 按一下印有 b 的按鍵,打字機凹槽中最後乙個字母...
NOI2011阿狸的打字機
剛學完字串演算法做一做題,這道題的質量的確很高,做完以後感覺對ac自動機有長進 一下的神仙思路來自yyb dalao 蒟蒻開始只想到了40分暴力,全程靠題解 step1 首先直接處理出所有的串再裸kmp好寫,但是覺得得分應該不高,也沒有人說能拿多少分 這個題正解的第一步是要想到ac自動機,準確地說和...
NOI2011 阿狸的打字機
調了下午到晚上 從0 40 70 100 心力交瘁 40分做法 直接在fail樹上暴力跳,修改節點值,樹狀陣列查詢時間複雜度n 2log 70分做法 接近正解,離線詢問,在對應的位置打標記,dfs的時候可以遍歷到這個點的時候,對這個點所有的詢問都可以同時處理出來 100分做法 讀入的時侯可以優化一下...