DTOJ#5127. 字串
你有兩個字串可重集合 S , T S, T S,T,初始時為空。
你要維護這兩個字串集合,支援加入和刪除字串,查詢這兩個集合的最大權匹配。
定義集合 S , T S, T S,T 的一組匹配方案為,有若干個二元組 ( s i , t i ) (s_i, t_i) (si,ti),其中 s i ∈ S , t i ∈ T , S , T s_i \in S, t_i \in T,S, T si∈S,ti∈T,S,T 中的每個元素最多出現在一個二元組中。
定義集合 S , T S, T S,T 一組匹配方案的權值為,$ \sum lcp(s_i, t_i)$,其中 l c p lcp lcp 表示最長公共字首。
第一行輸入 q q q,表示操作次數。
接下來 q q q 行,每行先輸入一個 t y p e type type。
-
若 t y p e = 1 type = 1 type=1,表示一次插入操作,接著讀入 c , s t c, st c,st, c ∈ { S , T } c \in \{S, T\} c∈{S,T} 表示插入的集合, s t st st 為插入的字串。
-
若 t y p e = 2 type = 2 type=2,表示一次刪除操作,接著讀入 k k k,表示刪除第 k k k 次操作插入的字元(保證第 k k k 次是插入,且未被刪除)。
q q q 行,每行輸出一個數,表示這次操作完後的最大權匹配。
樣例輸入
7
1 S aaab
1 T abccab
1 T ac
1 S abccde
2 4
1 S acc
1 T aaa
樣例輸出
0
1
1
5
1
3
5
樣例解釋
第 2 2 2 次操作完後,匹配為 ( a a a b , a b c c a b ) (aaab,abccab) (aaab,abccab)。
第 4 4 4 次操作完後,匹配為 ( a a a b , a c ) , ( a b c c d e , a b c c a b ) (aaab,ac),(abccde,abccab) (aaab,ac),(abccde,abccab)。
第 7 7 7 次操作完後,匹配為 ( a a a b , a a a ) , ( a c c , a c ) (aaab,aaa),(acc,ac) (aaab,aaa),(acc,ac)。
對於 20 % 20 \% 20% 的資料,保證 q ≤ 1000 q \leq 1000 q≤1000,任意時刻 ∣ S ∣ , ∣ T ∣ ≤ 1 \lvert S\rvert, \lvert T\rvert \leq 1 ∣S∣,∣T∣≤1。
對於 50 % 50 \% 50% 的資料,保證任意時刻 ∣ S ∣ , ∣ T ∣ ≤ 3 \lvert S|, \lvert T\rvert \leq 3 ∣S∣,∣T∣≤3。
另有 30 % 30 \% 30% 的資料,保證 q ≤ 80 , ∑ ∣ s t ∣ ≤ 500 q \leq 80, \sum \lvert st\rvert \leq 500 q≤80,∑∣st∣≤500。
對於 100 % 100 \% 100% 的資料,保證 q ≤ 500000 , ∑ ∣ s t ∣ ≤ 2 × 1 0 6 q \leq 500000, \sum\lvert st\rvert \leq 2 \times 10^6 q≤500000,∑∣st∣≤2×106,所有字元均為小寫字母。
首先最暴力的做法就是
n
2
n^2
n2列舉,考慮優化。
我們把列舉操作放到
t
r
i
e
trie
trie樹上,可以發現,我們遍歷到某一個節點,滿足字首已匹配,所以當前點一定可以匹配。考慮交換操作,這時發現
t
r
i
e
trie
trie樹若當前結點還支援匹配,則匹配操作相當於交換。。
所以貪心是正確的。
#include<bits/stdc++.h>
#define N 2000006
using namespace std;
int t[N][26],tot=1,cnt[N],ans,ty[N][2];
vector<char> in[N];
inline void add(int to,int val){
int w=1;
for(int i=0;i<in[to].size();++i){
int c=in[to][i]-'a';
if(!t[w][c])t[w][c]=++tot;
w=t[w][c];
if(cnt[w]*val<0)ans++;
cnt[w]+=val;
}
}
char ss[N],s[5];
int ad[2]={-1,1},len;
int main(){
int q,it=0;scanf("%d",&q);
for(int i=1;i<=q;++i){
int op;scanf("%d",&op);
if(op==1){
scanf("%s%s",s,ss);++it;len=strlen(ss);
for(int j=0;j<len;++j)in[it].push_back(ss[j]);
ty[i][0]=(s[0]=='S');ty[i][1]=it;
add(it,ad[s[0]=='S']);
}else{
scanf("%d",&op);add(ty[op][1],-ad[ty[op][0]]);ans-=in[ty[op][1]].size();
}
printf("%d\n",ans);
}
}
相關文章
- 字串-字串分割字串
- xml字串轉JSON字串XML字串JSON
- 字串-簡單字串排序字串排序
- 字串查詢(字串雜湊)字串
- 字串-簡單字串比較字串
- 字串字串
- 字串相乘——求字串的乘積字串
- MySQL 字串函式:字串擷取MySql字串函式
- JAVA字串轉日期或日期轉字串Java字串
- JS json字串轉物件、物件轉字串JSON字串物件
- JavaScript字串指定位置插入新字串JavaScript字串
- 字串1字串
- 字串操作字串
- 字串板子字串
- 字串指南字串
- string 字串字串
- 【字串】Manacher字串
- oracle 字串Oracle字串
- go 字串Go字串
- 字串相乘字串
- 「Redis」字串Redis字串
- java字串Java字串
- 字串匹配字串匹配
- PHP——字串PHP字串
- String字串字串
- 字串物件字串物件
- Python字串Python字串
- 【JavaScript】字串JavaScript字串
- 字串碎片字串
- Python字串講解舉例—工資字串!Python字串
- Python中的字串與字串格式化Python字串格式化
- ES6 - 字串模板與新增字串方法字串
- Java™ 教程(比較字串和字串的部分)Java字串
- Python科研武器庫 - 字串操作 - 字串分隔 split()、rsplit()Python字串
- 字串大小寫轉換和字串的比較字串
- BZOJ4259: 殘缺的字串(FFT 字串匹配)FFT字串匹配
- 字串常量池字串
- 字串專題字串