P3989 [SHOI2013]阶乘字符串(思维状压dp)
发布日期:2021-06-30 10:32:40 浏览次数:3 分类:技术文章

本文共 1300 字,大约阅读时间需要 4 分钟。

先建出序列自动机,那么可以在字符集的时间内判断一个串是不是阶乘字符串

如果枚举排列去验证复杂度不对,考虑 d p dp dp

然后发现状态的定义几乎只能这么定义

f [ i ] [ s ] f[i][s] f[i][s]表示前 i i i个字符满足状态为 s s s的字符集的阶乘字符串

但是发现并不好转移,在原来的基础上加入新的字符,无法判断是否能转移

重新定义状态

f [ s ] f[s] f[s]表示字符集为 s s s的阶乘字符串最早满足的位置是 [ 1 , f [ s ] ] [1,f[s]] [1,f[s]]

f [ s ] f[s] f[s]可以由状态 f [ a 1 ] , f [ a 2 ] , f [ a 3 ] . . . f[a_1],f[a_2],f[a_3]... f[a1],f[a2],f[a3]...转移而来

其中 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3之和 s s s相差一个字符

那么设 f [ a 1 ] f[a_1] f[a1]后面第一个出现的缺失字符位置在 q q q,那么 f [ s ] f[s] f[s]的答案至少是 q q q

f [ a 2 ] f[a_2] f[a2]后面第一个出现缺失字符的位置在 w w w,那么 f [ s ] f[s] f[s]的答案至少是 w w w

一次类推,我们不断取 m a x max max就能得到 f [ s ] f[s] f[s]的最小值

这样一定是一个阶乘字符串,因为我们考虑了每一个字符结尾的情况,而且结尾前都是阶乘字符串

#include 
using namespace std;const int maxn = 1e7+10;int t,n,f[maxn],nxt[1998][27];char a[maxn],b[maxn];int main(){
cin >> t; while( t-- ) {
cin >> n >> ( a+1 ); int len = strlen( a+1 ); if( n>21 ) {
cout << "NO\n"; continue; } for(int i=0;i<=26;i++) nxt[len][i] = 1e9; for(int i=len-1;i>=0;i--) {
for(int j=0;j<=25;j++) nxt[i][j] = nxt[i+1][j]; nxt[i][a[i+1]-'a'] = i+1; } memset( f,0,sizeof f ); for(int i=1;i<(1<
=1e9 ) f[i] = f[u]; else f[i] = max( f[i],nxt[f[u]][j] ); } } if( f[(1<
<=len ) cout << "YES\n"; else cout << "NO\n"; }} //Fe+O2=Fe3O4

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/116241504 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:P2627 [USACO11OPEN]Mowing the Lawn G(单调队列优化dp)
下一篇:P6793 [SNOI2020] 字符串(SAM树上贪心合并)

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月10日 17时40分23秒