*【CodeForces - 1150D】Three Religions(dp,预处理,思维)
題干:
During the archaeological research in the Middle East you found the traces of three ancient religions: First religion, Second religion and Third religion. You compiled the information on the evolution of each of these beliefs, and you now wonder if the followers of each religion could coexist in peace.
The?Word of Universe?is a long word containing the lowercase English characters only. At each moment of time, each of the religion beliefs could be described by a word consisting of lowercase English characters.
The three religions can coexist in peace if their descriptions form disjoint subsequences of the?Word of Universe. More formally, one can paint some of the characters of the?Word of Universe?in three colors:?11,?22,?33, so that each character is painted in?at most?one color, and the description of the?ii-th religion can be constructed from the?Word of Universe?by removing all characters that aren't painted in color?ii.
The religions however evolve. In the beginning, each religion description is empty. Every once in a while, either a character is appended to the end of the description of a single religion, or the last character is dropped from the description. After each change, determine if the religions could coexist in peace.
Input
The first line of the input contains two integers?n,qn,q?(1≤n≤1000001≤n≤100000,?1≤q≤10001≤q≤1000) — the length of the?Word of Universe?and the number of religion evolutions, respectively. The following line contains the?Word of Universe?— a string of length?nn?consisting of lowercase English characters.
Each of the following line describes a single evolution and is in one of the following formats:
- +?ii?cc?(i∈{1,2,3}i∈{1,2,3},?c∈{a,b,…,z}c∈{a,b,…,z}: append the character?cc?to the end of?ii-th religion description.
- -?ii?(i∈{1,2,3}i∈{1,2,3}) – remove the last character from the?ii-th religion description. You can assume that the pattern is non-empty.
You can assume that no religion will have description longer than?250250?characters.
Output
Write?qq?lines. The?ii-th of them should be?YES?if the religions could coexist in peace after the?ii-th evolution, or?NO?otherwise.
You can print each character in any case (either upper or lower).
Examples
Input
6 8 abdabc + 1 a + 1 d + 2 b + 2 c + 3 a + 3 b + 1 c - 2Output
YES YES YES YES YES YES NO YESInput
6 8 abbaab + 1 a + 2 a + 3 a + 1 b + 2 b + 3 b - 1 + 2 zOutput
YES YES YES YES YES NO YES NONote
In the first example, after the 6th evolution the religion descriptions are:?ad,?bc, and?ab. The following figure shows how these descriptions form three disjoint subsequences of the?Word of Universe:
題目大意:
給一個1e5的串str,然后有三個起始空串,不超過1000次操作,對三個字符串的一個尾部加一個字符或者減一個字符,保證每個字符不會超過250
每次操作之后詢問你這三個串是不是可以組成str的子序列,
比如ab,cd,ef可以組成acgbdef的子序列
解題報告:
[ i ][ j ] 代表的是在第j個位置之后的第i個字符的位置在哪里。
dp[ i ][ j ][ k ] 代表的是 匹配 第一個串前i個字符, 第二個串前j個字符, 第三個串前k個字符 這個狀態時 最后面一個字符在原串的位置的最小值。
如果題目把三個串給你,那么就應該是個n^3的dp。
但是這題并沒有這么善良,他的串是動態變化的。
比如,當操作為“+”的時候,如果添加的是s1,若s1的長度變為top[1]+1,可以發現,dp方程改變的只有dp [ top[1]+1] [ j ] [ k ] ,而其他的狀態值都沒有改變(因為只是在尾部操作,這點很關鍵)如果是s[2]也一樣,就是dp [ i ] [ top[2] + 1 ] [ k ] 。
而當操作為"-"的時候,我們并不需要更新dp數組,還是假設操作對象是s1,我們只能用到dp [ top[1] - 1 ] [ j ] [ k ] ,而這之前已經處理好了,而假設我們下一次需要“+”,自然會覆蓋dp [ top[1] ] [ j ] [ k ] 。所以不需要管。
對于某個字符下一次出現的位置,可以提前預處理出來。
所以總的復雜度為O(26n+250^2 * q)。
這題細節還是很多的。比如初始化的時候,需要初始化trie[n+1]? trie[n+2]這兩維,因為后面更新的時候要用到。(當然 能否用到就取決于你設置的非法狀態是多少,這里設置成n+1那么? 代碼匯總有可能用到 (n+1) + 1 這個狀態的值,也就是n+2了,,所以也要對這一維進行初始化。)
其次不是所有erase操作都直接輸出YES。因為萬一我模板串是 'aa' ,然后我對1號串+了100次 ' a ',那我erase98次都應該輸出NO才對。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 1e5 + 5; char ss[MAX]; int trie[MAX][28]; char s[4][MAX]; int top[4],up[4],down[4]; int dp[255][255][255]; int main() {int n,q;memset(dp,0x3f,sizeof dp);dp[0][0][0]=0;cin>>n>>q;cin>>(ss+1);for(int i = 0; i<=26; i++) trie[n+1][i] = trie[n+2][i] = n+1;ss[0] = 0;for(int i = n; i>=0; i--) {int cur = ss[i] - 'a';for(int j = 0; j<26; j++) {if(j == cur) trie[i][j] = i;else trie[i][j] = trie[i+1][j];}}char op[5],tmp[5];int id;while(q--) {scanf("%s",op);if(op[0] == '+') { scanf("%d",&id);scanf("%s",tmp);s[id][++top[id]] = tmp[0];for(int i = 1; i<=3; i++) down[i] = (i==id?top[i]:0),up[i] = top[i];for(int i = down[1]; i<=up[1]; i++) {for(int j = down[2]; j<=up[2]; j++) {for(int k = down[3]; k<=up[3]; k++) {dp[i][j][k] = n+1;if(i) dp[i][j][k] = min(dp[i][j][k],trie[dp[i-1][j][k]+1][s[1][i]-'a']);if(j) dp[i][j][k] = min(dp[i][j][k],trie[dp[i][j-1][k]+1][s[2][j]-'a']);if(k) dp[i][j][k] = min(dp[i][j][k],trie[dp[i][j][k-1]+1][s[3][k]-'a']); }}}}else {scanf("%d",&id);top[id]--;}if(dp[top[1]][top[2]][top[3]] > n) puts("NO");else puts("YES"); }return 0 ; }給幾個樣例理解一下dp,對每次詢問可以輸出一下dp[top[1]][top[2]][top[3]]的值看看。
/*
6 5
eabbcd
+ 1 a
+ 1 b
+ 2 b
+ 2 c
+ 3 e
?
6 5
eabbcd
+ 3 e
+ 1 a
+ 1 b
+ 2 b
+ 2 c
6 6
aaaaaa
+ 1 a
+ 1 a
+ 2 a
+ 2 a
+ 2 a
+ 3 a
*/
總結
以上是生活随笔為你收集整理的*【CodeForces - 1150D】Three Religions(dp,预处理,思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: smOutlookPack.exe -
- 下一篇: sms.exe - sms是什么进程