【Codeforces 1149 B】Three Religions
作者:互联网
题意:给一个字符串\(s\),现在有三个空串\(a、b、c\)。
有\(q\)个操作,每一个是
①给\(a、b、c\)中的一个末尾添加一个字符。
②把\(a、b、c\)中的一个末尾字符去掉。
每次操作后问是否可以将\(a、b、c\)分别作为\(s\)的一个不交叉的子序列。
思路:首先我们可以考虑\(dp\)。
设\(dp(l_a,l_b,l_c)\)表示现在\(a\)串匹配了\(l_a\)个,\(b\)串匹配了\(l_b\)个,\(c\)串匹配了\(l_c\)个,最小匹配到\(s\)串的第几位。
那么转移的时候枚举现在将要添加\(a、b、c\)串中哪一个的一个字符,
转移到\(dp(l_a+1,l_b,l_c)\)还是\(dp(l_a,l_b+1,l_c)\)还是\(dp(l_a,l_b,l_c+1)\)。
那么就发现我们要预处理出第\(i\)位后面第一个\(c\)字符在哪里,记为\(nxt(i,c)\)。
这样就可以\(O(1)\)转移了。状态数为\(O(len_a\times len_b\times len_c)\)。
但这样每一次操作后都要重算,十分浪费。
我们打个表观察一下每次操作后\(dp\)数组会有什么变化。
然后就可以发现:
①操作后只会添加\(l_i=len_i\)的所有状态,其中\(i\)为此次操作中修改的串。
②操作后不会改变任何\(dp\)值。
这样就好了。
因为有三个串,写起来十分不方便。
我转移的时候还把\(a[l_a+1]\)写了个\(a.back()\)上去。。。
标签:字符,匹配,1149,Codeforces,len,Religions,操作,转移,dp 来源: https://www.cnblogs.com/denverjin/p/10802620.html