梳理思路
从头开始吧
一:
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)即可;