BZOJ1590 [Usaco2008 Dec]Secret Message 秘密信息
阿新 • • 發佈:2019-01-28
解決 inline 有著 include com val getc ans ons
題意
貝茜正在領導奶牛們逃跑.為了聯絡,奶牛們互相發送秘密信息.
信息是二進制的,共有M(1≤M≤50000)條.反間諜能力很強的約翰已經部分攔截了這些信息,知道了第i條二進制信息的前bi(l《bi≤10000)位.他同時知道,奶牛使用N(1≤N≤50000)條密碼.但是,他僅僅了解第J條密碼的前cj(1≤cj≤10000)位.
對於每條密碼J,他想知道有多少截得的信息能夠和它匹配.也就是說,有多少信息和這條密碼有著相同的前綴.當然,這個前綴長度必須等於密碼和那條信息長度的較小者.
在輸入文件中,位的總數(即∑Bi+∑Ci)不會超過500000.
分析
參照jklover的題解。
將信息串插入 Trie 樹中,記錄子樹大小.詢問時,是密碼串前綴的,在搜索過程中會經過,密碼串是它的前綴的,到最後一個字符處加上子樹大小即可.
時間復雜度:線性。
代碼
實現起來有個細節,根節點必須是1。因為如果按密碼串匹配中途失敗之後,就不應該繼續匹配,而是一直停留在一個無效節點。所以把根節點設成1,然後無效節點自動為0,解決了這個技術問題。
#include<bits/stdc++.h> #define rg register #define il inline #define co const template<class T>il T read() { rg T data=0,w=1; rg char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') w=-1; ch=getchar(); } while(isdigit(ch)) { data=data*10+ch-'0'; ch=getchar(); } return data*w; } template<class T>il T read(rg T&x) { return x=read<T>(); } typedef long long ll; using namespace std; co int N=5e5+1; int tot=1,ch[N][2],val[N],siz[N]; int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); int n=read<int>(),m=read<int>(); while(n--) { int u=1,l=read<int>(); // edit 1:root must be 1 while(l--) { int b=read<int>(); if(!ch[u][b]) ch[u][b]=++tot; u=ch[u][b],++siz[u]; } ++val[u],--siz[u]; } while(m--) { int u=1,l=read<int>(),ans=0; while(l--) { int b=read<int>(); u=ch[u][b]; ans+=val[u]; } ans+=siz[u]; printf("%d\n",ans); } return 0; }
BZOJ1590 [Usaco2008 Dec]Secret Message 秘密信息