梅河口网站建设,怎样做网站设计,安徽股票配资网站建设,科技 网站 推荐CF1149B Three Religions
题意#xff1a;
给定长度为 n 的母串和三个子串s1,s2,s3s_1,s_2,s_3s1,s2,s3 。初始时子串均为空。有 q 次询问。你需要支持两种操作#xff1a;向某个子串末尾添加一个字母#xff0c;或者删去某个子串末尾的字母。在每次操作后#xff…CF1149B Three Religions
题意
给定长度为 n 的母串和三个子串s1,s2,s3s_1,s_2,s_3s1,s2,s3 。初始时子串均为空。有 q 次询问。你需要支持两种操作向某个子串末尾添加一个字母或者删去某个子串末尾的字母。在每次操作后你需要回答是否能从母串中分离出三个不相交的子序列不改变字符原有顺序满足这三个子序列恰好是s1,s2,s3s_1,s_2,s_3s1,s2,s3 在任意时刻,s1,s2,s3s_1,s_2,s_3s1,s2,s3的长度均不会超过 250
1≤n≤105,1≤q≤1031 \le n \le 10^5, 1\le q \le 10^31≤n≤105,1≤q≤103
题解
想了半天想不到真的想不到啊 dp题 设f[i][j][k]:表示匹配了A串的前i个字符(第i个字符选择了原串中x位置)B串匹配了前j个字符(第j个字符选择原串中y位置)C串匹配了前k个字符时(选择原串中z位置)至少需要到模式串的位置(max(x,y,z)) 数组s[i][0/1/2]:分别表示三个子串s1,s2,s3 我们需要一个nxt[i][c]来辅助转移表示在原串中[i,n]区间内c’字符第一次出现的位置 对着图nxt数组的含义很好理解。cf官方题解的图 现在我们开始考虑转移 当f[][][]n时就说明匹配失败 初始化f[i][j][k]n1,f[0][0][0]0 转移方程 f[i][j][k]min{nxt[f[i−1][j][k]1][s[1][i]],nxt[f[i][j−1][k]1][s[2][j]]nxt[f[i][j][k−1]1][s[3][k]]}f[i][j][k]min\{nxt[f[i-1][j][k]1][s[1][i]],nxt[f[i][j-1][k]1][s[2][j]]nxt[f[i][j][k-1]1][s[3][k]]\}f[i][j][k]min{nxt[f[i−1][j][k]1][s[1][i]],nxt[f[i][j−1][k]1][s[2][j]]nxt[f[i][j][k−1]1][s[3][k]]} 其实含义很简单我们就试图从A串中加个字符找后续位置从B串中价格字符找后续位置从C串中价格字符找后续位置从这个三个位置中选取最佳(即最左边)转移 对于每次插入我们只会在一个子串末端加另外两个不变那么新增状态只有新加字符与另外两个不变的串的位置关系这样有1∗250∗2501*250*2501∗250∗250种状态对于这些新状态重新跑就可以不用全部都重新跑 对于删除操作直接减小对应串长。因为我们之前转移时小的状态都算好了所以直接减对应的串长就可以得到新的答案 答案就是ans[f[len1][len2][len3]]ans[f[len1][len2][len3]]ans[f[len1][len2][len3]],表示三个串全部匹配完之后在模式串中的最左点。对于样例来说就是如图三个位置取最大值。如果n说明有解如果n说明无解
代码
#include bits/stdc.h
#include unordered_map
#define debug(a, b) printf(%s %d\n, a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pairint, int PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll 1e18;
const int INF_int 0x3f3f3f3f;
void read(){};
template typename _Tp, typename... _Tps void read(_Tp x, _Tps... Ar)
{x 0;char c getchar();bool flag 0;while (c 0 || c 9)flag| (c -), c getchar();while (c 0 c 9)x (x 3) (x 1) (c ^ 48), c getchar();if (flag)x -x;read(Ar...);
}
template typename T inline void write(T x)
{if (x 0) {x ~(x - 1);putchar(-);}if (x 9)write(x / 10);putchar(x % 10 0);
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#elsestartTime clock ();freopen(data.in, r, stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime clock();printf(\nRun Time:%lfs\n, (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn2e59;
int s[4][300];
int nxt[maxn][30];
int f[300][300][300];
int len[4];
int n,q;
char str[maxn];
void init(){for(int i0;i26;i)nxt[n1][i]nxt[n2][i]n1;for(int in;i;i--){for(int j0;j26;j){if(str[i]ja)nxt[i][j]i;else nxt[i][j]nxt[i1][j];}}
}
void solve(){char ch;cinch;int id;read(id);if(ch){cinch;s[id][len[id]]ch-a;for(int i(id1?len[1]:0);ilen[1];i){for(int j(id2?len[2]:0);jlen[2];j){for(int k(id3?len[3]:0);klen[3];k){int nown1;if(i)nowmin(now,nxt[f[i-1][j][k]1][s[1][i]]);if(j)nowmin(now,nxt[f[i][j-1][k]1][s[2][j]]);if(k)nowmin(now,nxt[f[i][j][k-1]1][s[3][k]]);f[i][j][k]now;}}}}else if(ch-){len[id]--;}coutf[][][]f[len[1]][len[2]][len[3]]endl;if(f[len[1]][len[2]][len[3]]n)puts(YES);else puts(NO);
}
int main()
{//rd_test();read(n,q);scanf(%s,str1);init();while(q--)solve();return 0;//Time_test();
}