洛谷4965 薇爾莉特的打字機(Trie,DP)

2022-05-11 03:49:14 字數 1124 閱讀 4520

神仙題。

考慮在一棵 trie 上進行染色,將可能出現的串的末尾染成黑色。答案就是黑點的個數。一開始只有 \(a\) 的末尾點是黑色。

當出現乙個字元(不是退格)\(c\) 時,就要將每個黑點的 \(c\) 兒子都染成黑色。

然而這樣乙個點可能會有重複染色,不能直接乘 \(2\)。

不妨記錄乙個 \(f[c]\) 表示有兒子 \(c\) 且該兒子是黑色的點的個數。

那麼此時答案 \(ans\) 應該變成 \(2ans-f[c]\)(減掉已經是黑的兒子 \(c\) 的個數),同時更新一下 \(f[c]\),就是原來的 \(ans\)(原來的每個黑點都有乙個黑兒子 \(c\))。其它的 \(f\) 不變。

當出現退格時:

退格實際上就是回到 trie 上的父親。

我們發現,乙個字元不打,和打了再被退格是一樣的。所以退格有用,當且僅當它刪掉的是原來 \(a\) 串裡的字元。

再仔細分析一波,如果是第 \(x\) 個退格,那麼收到影響的點只有 \(a[n-x+1]\) 這個點。

(可以通過 trie 理解,除了最淺的黑點,其它的黑點的父親肯定都是黑點,所以只用考慮最淺的黑點,也就是 \(a[n-x+1]\) 這個點)

對這個點瞎搞一波就行了。

時間複雜度 \(o(n+m)\)。

#includeusing namespace std;

const int maxn=5000500,mod=19260817;

#define lson o<<1,l,mid

#define rson o<<1|1,mid+1,r

#define for(i,a,b) for(int i=(a);i<=(b);i++)

#define rof(i,a,b) for(int i=(a);i>=(b);i--)

#define mem(x,v) memset(x,v,sizeof(x))

inline int read()

int n,m,f[26],ans=1,at;

char a[maxn],b[maxn];

int main()

else

} printf("%d\n",ans);

}

P4965 薇爾莉特的打字機

只要客人有意向,不論身在何處,都能上門服務。我是自動手記人偶服務 薇爾莉特 伊芙加登。薇爾莉特的打字機用了太久,按鍵已經開始老化了,因此有時候按鍵會沒有反應。而薇爾莉特總是盲打,因此按鍵沒反應她也不會注意到。一天,她用這台打字機繼續完成一封還沒寫完的信。現在告訴你這封信已經寫好的部分以及薇爾莉特想進...

題解 薇爾莉特的打字機

首先,這題需要處理字串,我們用 trie分析 先忽略刪除操作 拿樣例 1 舉個例子 首先把最開始的字串插入到樹中 然後薇爾莉特打了乙個字元 a 此時可以插入或者是不插入,就會有這樣的情況 不插入時,之前插入進去的字元均可以作為字串的結尾 假設之前插入了 x個字母,每乙個字母都可以作為串的結尾 現在插...

薇爾莉特的打字機題解

好題 就是我死活想不到,看題解後卻不得不佩服思路巧妙的題 我們將一種字串看做乙個點 每一次操作就是對所有存在的點進行拓展 不按,狀態不變 按下,狀態增加 這就是先按a後按b的例子。1.輸入乙個字母 所有子樹中沒有此字母的點會增加,所以我們用乙個陣列 f x 記載沒有此字母 x 的點數 之後,原來的所...