• 2023icpc网络预选赛I. Pa?sWorD(dp)


    题目给定字符串长度n以及字符串s

    其中出现小写字母可以代表小写字母和大写字母  比如'a'可以代表'a'和'A'

    出现'?'可以代表26个小写字母和26个大写字母和10个数字

    出现大写字母和数字就是原本的数

    同时要求大写字母,小写字母,数字一定都存在替换完的字符串

    相邻的字母不能相同

    思路

    dp[2][70][8]

    第一维代表用来存前一个当前状态和前一个状态

    70用来存当前的字符

    0-25代表小写字母,26-51代表大写字母,52-61代表大写字母,62代表什么都没有也就是初始状态

    8用二进制状态压缩存是否出现过大写,小写,数字

    _ _ _第一个存是否出现大写,第二个小写,第三个数字

    从前往后枚举

    当出现'?'

    枚举61中可能(i),然后从前面62种状态(j)所有k继承

    假如i是小写字母的话

    如果i==j 就continue

    其他情况dp[now][i][(k|(1<<2))]+=dp[pre][j][k]

    同理i是大写的话就

    dp[now][i][(k|(1<<1))]+=dp[pre][j][k]

    但是这是一个o(64*64*8*100000)

    会超时

    你可以发现从前一个状态继承的就是62种状态之和减去唯一一个与当前转台不同的就行了

    1. const int inf=0x3f3f3f3f3f3f3f3f,N=1e5+5,mod=998244353;
    2. int dp[2][70][8];
    3. int jian(int x,int y) {
    4. return ((x-y)%mod+mod)%mod;
    5. }
    6. signed main() {
    7. ios_base::sync_with_stdio(0);
    8. cin.tie(0),cout.tie(0);
    9. int n;
    10. cin>>n;
    11. string s;
    12. cin>>s;
    13. s=' '+s+' ';
    14. for(int i=1; i<=n; i++) {
    15. int now=i&1,pre=1-now;
    16. if(i==1) {
    17. dp[pre][62][0]=1;
    18. }
    19. for(int j=0; j<=62; j++) {
    20. for(int k=0; k<=7; k++) {
    21. dp[now][j][k]=0;
    22. }
    23. }
    24. vector<int>a(10);
    25. for(int j=0; j<=62; j++) {
    26. for(int k=0; k<=7; k++) {
    27. a[k]+=dp[pre][j][k];
    28. a[k]%=mod;
    29. }
    30. }
    31. if(s[i]=='?') {
    32. for(int j=0; j<26; j++) {
    33. for(int k=1; k<=7; k++) {
    34. for(int w=0; w<=7; w++) {
    35. if((w|(1<<2))==k) {
    36. dp[now][j][k]+=jian(a[w],dp[pre][j][w]);
    37. dp[now][j][k]%=mod;
    38. }
    39. }
    40. }
    41. }
    42. for(int j=26; j<52; j++) {
    43. for(int k=1; k<=7; k++) {
    44. for(int w=0; w<=7; w++) {
    45. if((w|(1<<1))==k) {
    46. dp[now][j][k]+=jian(a[w],dp[pre][j][w]);
    47. dp[now][j][k]%=mod;
    48. }
    49. }
    50. }
    51. }
    52. for(int j=52; j<62; j++) {
    53. for(int k=1; k<=7; k++) {
    54. for(int w=0; w<=7; w++) {
    55. if((w|(1<<0))==k) {
    56. dp[now][j][k]+=jian(a[w],dp[pre][j][w]);
    57. dp[now][j][k]%=mod;
    58. }
    59. }
    60. }
    61. }
    62. }
    63. else if(s[i]>='a'&&s[i]<='z') {
    64. for(int j=s[i]-'a'; j<=s[i]-'a'; j++) {
    65. for(int k=1; k<=7; k++) {
    66. for(int w=0; w<=7; w++) {
    67. if((w|(1<<2))==k) {
    68. dp[now][j][k]+=jian(a[w],dp[pre][j][w]);
    69. dp[now][j][k]%=mod;
    70. }
    71. }
    72. }
    73. }
    74. for(int j=s[i]-'a'+26; j<=s[i]-'a'+26; j++) {
    75. for(int k=1; k<=7; k++) {
    76. for(int w=0; w<=7; w++) {
    77. if((w|(1<<1))==k) {
    78. dp[now][j][k]+=jian(a[w],dp[pre][j][w]);
    79. dp[now][j][k]%=mod;
    80. }
    81. }
    82. }
    83. }
    84. } else if(s[i]>='A'&&s[i]<='Z') {
    85. int t=s[i]-'A'+26;
    86. for(int k=1; k<=7; k++) {
    87. for(int w=0; w<=7; w++) {
    88. if((w|(1<<1))==k) {
    89. dp[now][t][k]+=jian(a[w],dp[pre][t][w]);
    90. dp[now][t][k]%=mod;
    91. }
    92. }
    93. }
    94. } else {
    95. int t=s[i]-'0'+52;
    96. for(int k=1; k<=7; k++) {
    97. for(int w=0; w<=7; w++) {
    98. if((w|(1<<0))==k) {
    99. dp[now][t][k]+=jian(a[w],dp[pre][t][w]);
    100. dp[now][t][k]%=mod;
    101. }
    102. }
    103. }
    104. }
    105. // for(int i=0;i<62;i++){
    106. // for(int k=0;k<=7;k++){
    107. // cout<
    108. // }
    109. // cout<<"\n";
    110. // }
    111. // cout<<"--------------------\n";
    112. }
    113. int sum=0;
    114. for(int i=0; i<62; i++) {
    115. sum+=dp[(n&1)][i][7];
    116. sum%=mod;
    117. }
    118. cout<"\n";
    119. }

  • 相关阅读:
    递归、搜索与回溯算法:FloodFill 算法
    【初中生讲机器学习】12. 似然函数和极大似然估计:原理、应用与代码实现
    TypeScript入坑
    el-tree自定义节点内容
    基于神经网络的车牌识别系统在matlab上如何实现
    PCM、WAV,立体声,单声道,正弦波等音频素材
    Could not load dynamic library ‘cudart64_110.dll‘的解决方法
    安科瑞餐饮油烟监测云平台助力大气污染攻坚战
    英语学习:D开头
    网络流量分类概述
  • 原文地址:https://blog.csdn.net/m0_74315028/article/details/132957212