SPOJ8093 Sevenk Love Oimaster 廣義SAM、樹狀數組
阿新 • • 發佈:2019-02-26
插入 n) 解決 begin ++i namespace efi rst iii
傳送門
對於所有模板串建立廣義\(SAM\),插入第\(i\)個串的過程中給經過的點打上第\(i\)種標記;然後將每一個詢問串放在\(SAM\)上跑一邊得到該串對應在\(SAM\)的狀態,如果為空答案就是\(0\),否則我們需要求這個狀態的標記數量。
因為如果某個串被打了某些標記,那麽它在\(parent\)樹上的祖先也要有這些標記。所以問題等價於:某個點在\(parent\)樹上的子樹中有多少種標記,放到\(parent\)樹的\(dfs\)序上就是HH的項鏈。將詢問離線,跑出dfs序然後樹狀數組解決。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cctype> #include<vector> #include<queue> #include<cstring> #include<algorithm> //This code is written by Itst using namespace std; int N , M; const int MAXN = 2e5 + 7; namespace SAM{ int Lst[MAXN] , Sst[MAXN] , fa[MAXN] , trans[MAXN][26]; int cnt = 1 , L; char s[MAXN]; vector < int > col[MAXN]; int insert(int p , int len , int x){ int t = ++cnt; Lst[t] = len; while(p && !trans[p][x]){ trans[p][x] = t; p = fa[p]; } if(!p){ Sst[t] = fa[t] = 1; return t; } int q = trans[p][x]; Sst[t] = Lst[p] + 2; if(Lst[q] == Lst[p] + 1){ fa[t] = q; return t; } int k = ++cnt; memcpy(trans[k] , trans[q] , sizeof(trans[k])); Lst[k] = Lst[p] + 1; Sst[k] = Sst[q]; Sst[q] = Lst[p] + 2; fa[k] = fa[q]; fa[q] = fa[t] = k; while(trans[p][x] == q){ trans[p][x] = k; p = fa[p]; } return t; } vector < int > ch[MAXN]; int dfn[MAXN] , sz[MAXN] , ind[MAXN] , ts; void dfs(int x){ dfn[x] = ++ts; ind[ts] = x; sz[x] = 1; for(int i = 0 ; i < ch[x].size() ; ++i){ dfs(ch[x][i]); sz[x] += sz[ch[x][i]]; } } void init(){ for(int i = 2 ; i <= cnt ; ++i) ch[fa[i]].push_back(i); dfs(1); } #define PII pair < int , int > #define st first #define nd second #define PIII pair < PII , int > #define lowbit(i) ((i) & -(i)) int ans[MAXN] , BIT[MAXN] , bef[MAXN]; vector < PIII > query; PII go(){ scanf("%s" , s + 1); int L = strlen(s + 1) , cur = 1; for(int i = 1 ; i <= L ; ++i) if(trans[cur][s[i] - 'a']) cur = trans[cur][s[i] - 'a']; else return PII(0 , 0); return PII(sz[cur] + dfn[cur] - 1 , dfn[cur]); } void modify(int x , int num){ if(!x) return; while(x <= cnt){ BIT[x] += num; x += lowbit(x); } } int get(int x){ int sum = 0; while(x){ sum += BIT[x]; x -= lowbit(x); } return sum; } void work(){ for(int i = 1 ; i <= M ; ++i){ PII t = go(); if(t.st) query.push_back(PIII(t , i)); } sort(query.begin() , query.end()); int cur = 0; for(int i = 0 ; i < query.size() ; ++i){ while(cur < query[i].st.st){ ++cur; for(int j = 0 ; j < col[ind[cur]].size() ; ++j){ modify(bef[col[ind[cur]][j]] , -1); modify(bef[col[ind[cur]][j]] = cur , 1); } } ans[query[i].nd] = get(query[i].st.st) - get(query[i].st.nd - 1); } for(int i = 1 ; i <= M ; ++i) cout << ans[i] << endl; } } namespace Trie{ int ch[MAXN][26] , dep[MAXN] , ind[MAXN] , cnt = 1; char s[MAXN]; vector < int > col[MAXN]; void insert(int c){ scanf("%s" , s + 1); int L = strlen(s + 1) , cur = 1; for(int i = 1 ; i <= L ; ++i){ if(!ch[cur][s[i] - 'a']){ ch[cur][s[i] - 'a'] = ++cnt; dep[cnt] = dep[cur] + 1; } cur = ch[cur][s[i] - 'a']; col[cur].push_back(c); } } void build(){ queue < int > q; q.push(ind[1] = 1); while(!q.empty()){ int t = q.front(); q.pop(); for(int i = 0 ; i < 26 ; ++i) if(ch[t][i]){ ind[ch[t][i]] = SAM::insert(ind[t] , dep[ch[t][i]] , i); SAM::col[ind[ch[t][i]]] = col[ch[t][i]]; q.push(ch[t][i]); } } SAM::init(); } } int main(){ #ifndef ONLINE_JUDGE freopen("in" , "r" , stdin); //freopen("out" , "w" , stdout); #endif cin >> N >> M; for(int i = 1 ; i <= N ; ++i) Trie::insert(i); Trie::build(); SAM::work(); return 0; }
SPOJ8093 Sevenk Love Oimaster 廣義SAM、樹狀數組