梳理思路

从头开始吧


一:

T1:Censoring(字符串hash)

hash+灵活运用+神仙思路:

jg[]表示答案串,c[]是读入串,lhash[]表示新字符串的hash值,shash[]表示原字符串的hash值

用两个指针js表示最后输出字符串的长度,zz表示原字符串加到哪了,

每从原字符串里往答案加一个新字符,就从枚举一遍n个的单词的列表看哪个单词能删,就把js-=该单词长度

删完一个就break掉,防止算重(不知道会不会)

核心代码

T2:记忆的轮廓(大神概期+DP)

(1)首先,要先读懂题,认真读
     譬如:数据保证j是k的父亲,建单向边;
         走到错误叶子才会读档 !错误节点;
         走到错误叶子读档还要再走一步才能回去;
   ***注意:又是一道有t的题,记得清零;***
(2)其次,
     one:既然有存档这个神奇的东西,dp是一定是二维的;
     所以设f[i][j](i为当前正确节点,还剩j次存档机会到n的期望步数)
     则f[i][j]=min(f[i][j],从i到k的期望步数+f[k][j-1]) i+1<=k<=n;
     ***注意:初始化时只有f[n][0]=0;***
       因为f[n-1][0]即走到n-1时就没有存档机会了,而题中说1,n两点必须存档,
       所以其他的f值都是最大值;
     two:维护从i到j的期望步数dp[i][j](i,j均为正确节点且i,j中间不存档)
      则dp[i][j]=dp[i][j-1]+从j-1到j的期望步数;
          从j-1到j的期望步数=从j-1直接到j的期望+从j-1走到错误叶子再走一步再回到i再到j的期望;
      用g[i]维护从错误节点i走到错误叶子再走一步的期望步数;
      则g[i]=sigma((1/du[i])*g[j]+1)=1+(1/du[i])+sigma(g[j]);(j是i的儿子)
      用s[i]记录正确节点i所有错误儿子的g值和;
      设d=d[j-1];
      即可得dp[i][j]=dp[i][j-1]+(1/d)/*j-1直接到j*/+sigma((1/d)*(1/*从j-1到他儿子k的一步*/+g[k]+dp[i][j]))(sigma要除去正确节点)
                =dp[i][j-1]+(1/d)+((d-1)/d)*(1+dp[i][j])+sigma((1/d)*g[k]);                     
                      |------->定值<-------| |---->即s[i]<----|
      等式两边同乘d,把dp[i][j]移到左边得dp[i][j]=dp[i][j-1]*d+d+s[j-1];
    最后输出f[1][p-1]即可 因为1必须存档;
      three:建树
        因为只连了错误节点的边,所以从1到n-1都要dfs一遍,dfs前du别忘了加自己的一个正确儿子;
        dfs同时处理g,s;
      four:玄幻的时间优化
       因为dp数组增速很快,所以如果i与j相差40以上dp[i][j]已经是极大值对答案没有贡献,因此j只需要枚举到min(n,i+40)即可;

原文地址:https://www.cnblogs.com/qwertyuiopasdfghjklzxcvbnm/p/11670733.html