題目鏈結
填乙個很久以前用 \(\texttt\) 自動機沒填上的坑。
關於本題,能夠通過本題的演算法很多,這裡作者採用的是字尾陣列+樹狀陣列的做法。
首先有乙個顯然的結論:若 \(s_2\) 是 \(s_1\) 的子串,則 \(s_1\) 一定存在乙個字尾與 \(s_2\) 的最長公共字首為 \(|s_2|\)。
我們將讀入的姓、名、詢問串連成乙個整體,形成乙個字串 \(s\),且在每乙個姓、名、詢問串中插入乙個不存在文字中的字元,且保證詢問串後插入的比姓名串後插入的字元字典序小。
然後我們求出字串 \(s\) 的 \(\texttt\) 陣列,將兩字尾的 \(\texttt\) 轉化為 \(\texttt\) 問題。
根據上面我們的構造方式可以得到:如果乙個詢問可以被響應,那麼\(\texttt\) 陣列中一定存在下標連續的一段,它們所代表的字尾的 \(\texttt\) 等於詢問串長度,且這一段的開頭一定是以這個詢問串開頭的字尾。
原因也很簡單,因為我們在詢問串後插入的分割字元是比插入在姓名串後的字元小的,所以按照字尾大小排序後自然排在相對靠前的位置。
這啟發我們可以通過二分查詢右端點(左端點已經確定,就是詢問串開頭的字尾),將每個詢問轉化成乙個區間,然後問題轉化為:
問題一是乙個經典問題,即區間內有多少種不同的顏色。可以用離線後用樹狀陣列完成,這裡給出一種具體做法(不唯一):將每個詢問固定至其右端點上,從小到大列舉右端點,在樹狀陣列中將每種顏色最靠近右端點(不超過右端點)的位置加 \(1\) 統計,這樣可以保證最優。所以我們需要維護乙個 \(\texttt\) 陣列,表示當前位置顏色上一次出現的位置。
問題二在我們維護了 \(\texttt\) 陣列過後也變得較為簡單。首先將每個區間在樹狀陣列上加 \(1\)。仍然將每個區間固定至其右端點,列舉右端點,計算每個點的貢獻,即 \(sum(i)-sum(pre[i])\),然後將以當前位置為右端點的區間在樹狀陣列上減 \(1\)。
至此,本題可以在 \(o(|s|log_2|s|)\) 的複雜度內解決。
貼**(人傻自帶大常數)
#includeusing namespace std;
const int maxn=3e5+5;
int s[maxn];
int sa[maxn],rk[maxn],tp[maxn],cnt[maxn];
int nn,n,m,q;
int height[maxn],h[maxn];
int col[maxn],len[maxn],vis[maxn];
int mn[maxn][21],lg[maxn];
int tree[maxn];
int l[maxn],r[maxn],tot;
int lst[maxn],pre[maxn];
int ans1[maxn],ans2[maxn];
vector> v[maxn];
vectorv2[maxn];
inline void add(int x,int k)
inline int sum(int x)
inline void sort()
inline void init()
for(int i=1;i<=n;++i) rk[sa[i]]=i;
int k=0;
for(int i=1;i<=n;++i)
}int main()
for(int i=1;i<=q;++i)
s[++n]=-i+q;
} sa();
init();
for(int i=1;i<=n;++i)
else r=mid-1;
}v[ans].emplace_back(i,vis[sa[i]]);//二分求右焦點
l[++tot]=i,r[tot]=ans+1;//這裡儲存的區間是[l,r+1],所以後面就不用+1了
} if(col[sa[i]])
} for(int i=1;i<=n;++i)
for(auto x:v[i])
ans1[x.second]=sum(i)-sum(x.first-1);
}//問題一
memset(tree,0,sizeof tree);
for(int i=1;i<=tot;++i) add(l[i],1),add(r[i],-1),v2[r[i]].emplace_back(l[i]);
for(int i=1;i<=n;++i)//問題二
for(int i=1;i<=q;++i) cout
SCOI2012 喵星球上的點名
有n個串,代表n個人的姓氏和名字,都是用很多個數字表示的,比如我姓1,2,3,4,名4,5,6,7。然後有m個點名串,如果點到了某個人的姓或名裡面的某一串,那個人就被點到,不過乙個人在乙個點名串中只能被點一次。比如點名串是2,3,4,我的姓中含有2,3,4,那麼我就會被叫到。求每個學生分別被叫到多少...
SCOI2012 喵星球上的點名
給出n個模式串,m個文字串,每個模式串由兩部分組成,我們認為乙個模式串被乙個文字串包含只要這個文字串包含它的兩部分中的其中一部分的子串。求每個文字串包含多少個模式串,每個模式串又被多少個文字串包含。1 n 20000,1 m 50000,模式串總長和文字串的總長分別不超過100000 保證模式串和文...
SCOI2012 喵星球上的點名
對於第乙個詢問,對於姓名串建廣義字尾自動機,那麼我們對於插入乙隻喵的姓名串,要將這兩個 姓和名 串的所有字串位置打標記,怎麼搞呢,其實可以直接插入暴力向上跳,複雜度的話 對於乙個串假設長度為x,那麼插入複雜度是min x x,x n 而最多只有n x個這樣的串,算一下總的複雜度上界是n根號的。然後就...