首页 > 其他分享 >字符串杂杂杂杂杂杂题

字符串杂杂杂杂杂杂题

时间:2022-10-04 17:00:08浏览次数:47  
标签:子串 杂杂 lcp max 杂杂题 字符串 now dp

[CF1310C] Au Pont Rouge

首先,肯定要将所有的代价给弄出来,若先不管划分段数的限制,那么所有代价就是\(S\)的所有字串

那么字串的数量也就是\(\frac{n*(n+1)}{2}\),约为\(10^6\)的范围

既然答案要求一个准确的字符串,所以考虑二分答案,首先对所有的代价进行排序(\(lcp\)轻松搞定)

对于当前二分的字符串\(s_{now}\),check函数内用dp进行判断

\(dp[i][j]\)为\(s[i,n]\),划分成\(j\)段的方案数

\[dp[i][j]=\sum_{k>i\&\&s[i,k-1]\geqslant s_{now}} dp[k][j-1] \]

复杂度是\(O(n^3)\)的,所以想办法把这个\(k\)做掉

后面这个\(\sum_{k>i\&\&s[i,k-1]\geqslant s_{now}} dp[k][j-1]\)显然是一个后缀和可以\(O(1)\)解决的

对于字符串\(a,b\),设\(a[1,i-1]==b[1,i-1]\&\&a[i]!=b[i]\ \ (i<min(len_a,len_b))\)

若\(a[1,i]>b[1,i]\),则对于\(a\)的每个结尾处\(\geqslant i\)的前缀,其字典序都大于\(b\)

否则,\(a\)的所有前缀的字典序都小于\(b\)

然后,距离做掉\(k\)还差一部,就是如何\(O(1)\)找到第一个\(k\)

这时,就又可以上\(lcp\)了

设\(t\)为\(min\{s[i,n]与s_{now}的lcp,len_{s_{now}}\}\)

当\(t==len_{s_{now}}\)或者\(s_{now}\)的第\(t+1\)个字符小于\(s[i+t]\)时,第一个\(k\)就是\(t+1\)

否则,就不存在\(k\)(见上面注释起来的文字说明)

然后,就完了

[CF1701E] Text Editor

可以将\(s\)划分成三段

一段为从左往右删(可为空),一段为不删,一段为从右向左删(可为空)

那么操作的整体流程就是:从右向左删,遇到不删的区域,跳到左边去,然后从左往右删,遇到不删的区域,结束

根据这个方法,可以先定义出一个三位dp

\(dp[i][j][0/1/2]\),\(t[i]\)与\(s[j]\)匹配(可以是对应关系,也可以是\(s[j]\)被删掉)

\[dp[i][j][0]=min\{dp[i][j-1][0]+2,dp[i-1][j-1][0]+2(t[i]==s[j])\} \]

\[dp[i][j][2]=min\{dp[i][j-1][1]+1,dp[i][j-1][2]+1,dp[i-1][j-1][2]+1(t[i]==s[j])\} \]

\[dp[i][j][1]=min_{t[i]==s[j]}\{dp[i-1][j-1][0],dp[i-1][j-1][1](t[i-1]==s[j-1])\} \]

然后就是因为\(1\leqslant len_t\leqslant len_s\leqslant5000\),所以会\(MLE\),将\(j\)压成\(0/1\)就行了

[CF150D] Mission Impassable

看到\(l\)的范围,\(1\leqslant l\leqslant 150\),区间DP的\(O(n^3)\)可以上了

设\(dp[i][j]\)为操作完\(s[i,j]\)后的最大权值,那么\(dp[i][j]\)有两种选择:全部删完或只删一部分,记\(f[i][j]\)为将\(s[i,j]\)全部删完后的最大权值

\[dp[i][j]=max\{0,f[i][j],dp[i][k]+dp[k+1][j]\} \]

然后,解决\(f[i][j]\),因为删的方式可以十分杂乱,也就是可以分成好几个区间删除并且删除其中几个后又可以将一些区间合并然后继续,所以,不能直接上区间dp

而对于所有的区间,最后一步一定是删掉一个长度为\(k\)的回文串,所以我们考虑设\(g[i][j][k]\)为\(s[i,j]\)最后一步删掉一个长度为\(k\)的回文串的最大代价(不算删掉这个长度为\(k\)的回文串的代价)

也可以算上,主要是如果算上了代码里要写很多个\(+val[k]\),太麻烦了

如果\(s[i]\)与\(s[j]\)不一起删

\[g[i][j][k]=max_{l\leqslant p<r}\{g[l][p][k]+f[p+1][r],f[l][p]+g[p+1][r][k]\} \]

如果一起删,且分别为区间的两端

\[g[i][j][k]=max\{g[i+1][j-1][k-2]\} \]

那么

\[f[i][j]=max\{g[i][j][k]+val[k]\} \]

然后答案就是\(dp[1][n]\)

[SNOI2019]字符串

比较简单啊,找规律

考虑字符串\(aabcd\)

比较删除第一个\(a\)与删除\(b\)的字符串的大小:

a\(abcd\)

\(aa\)b\(cd\)

可与发现,若删除字符\(s[i]\)与字符\(s[j]\ \ (i<j)\),需要比较的区间就是\(s[i+1,j-1]\),并且,若删去相邻且相同的字符,得到的字符串的字典序相同

所以,可以将原字符\(S\)串变成一个新的字符串\(T\),即将原字符串中相邻且相等的字符变成同一个字符,若\(S[i]\)与\(S[i+1]\)同属于一个\(T[k]\),那么在排序中,\(i\)和\(i+1\)一定挨在一起,且\(i\)在\(i+1\)的前面

若\(S[i]\)与\(S[j]\)不同属一个\(T[j]\),设\(S[i]\)属于\(T[bel[i]]\),\(S[j]\)属于\(T[bel[j]]\),就只需要比较\(T[bel[i]]\)与\(T[bel[i]+1]\)的大小,若大于,则\(i\)的排名小于\(j\),否则大于\(j\),于是就只需要比较每个\(T[i]\)与\(T[i+1]\)的大小,然后用一个类似后缀和什么的东西就可以\(O(n)\)解决了

[CF1422E] Minlexes

对于题目进行一个解释:

\(abba\ \ \rightarrow \ \ aa\ \ \nrightarrow\) aa

设\(f[i]\)为删掉\(s[i,n]\)的最小字符串

若\(s[i]\not= s[i+1]\),则\(f[i]=s[i]+f[i+1]\)

否则,可以选择\(s[i]\)与\(s[i+1]\)一起删

当\(s[i]>f[i+2][0]\)时,删掉

当\(s[i]<f[i+2][0]\)时,不删,\(f[i]=s[i]+s[i]+f[i+2]\)

若\(s[i]==f[i+2][0]\),设\(f[i+2]\)的第一个与\(f[i+2][0]\)不相等的字符为\(dif\)

若\(dif>f[i+2][0]\),删

否则,不删

然后就是\(f\)可能会\(MLE\),我的方法比较笨,就是当\(f[i].size()>10\)时,将它直接变成题目要求的样子,所以我们需要一个单独的数组来记录每个\(f[i]\)的真实长度,再用一个\(dif\)数组记录\(f[i]\)的第一个与\(f[i][0]\)不相等的字符,就可以了

[CF1562E] Rescue Niwen!

自己简单搞个字符串模一模,就可以发现排好序后的序列呈一个分成\(n\)段,第\(i\)段中的所有字串的开头都是\(s[i]\),且整个段内为上升序列

一个段内的形式大概如下:\(a\) \(ab\) \(abc\) \(abcd\)

也就是说,若选了该段中的第\(i\)个串,则从\(i\)到段末的串都可以选择

这启示我们,若答案的最长序列中以第\(i\)段中的子串结尾,则答案末尾的这个子串一定是第\(i\)段的末尾的子串

还有,若可以由第\(j\)段中的第\(k\)个子串到达第\(i\)段的第\(l\)个子串,那么第\(j\)段的\(k\)个到最后一个子串都可以到达第\(i\)段中的第\(l\)个字串

因为第\(j\)段中的第\(k\)个子串已经小于第i段的第\(l\)个子串了,所以无论在第\(k\)个子串后面加多少个字符,都会小于第\(l\)个子串

所以,上dp

\(dp[i]\)表示以第\(i\)段的最后一个字串为序列的结尾的最长序列,\(lcp[i][j]\)表示\(s[i,n]\)与\(s[j,n]\)的\(lcp\)

\[dp[i]=max_{j<i\&\&lcp[i][j]<n-i+1\&\&s[i+lcp[i][j]]>s[j+lcp[i][j]}\{n-i+1,dp[j]+n-i+1-lcp[i][j]\} $$\]

ans=max{dp[i]}

\[\]

标签:子串,杂杂,lcp,max,杂杂题,字符串,now,dp
From: https://www.cnblogs.com/LuoyuSitfitw/p/16754049.html

相关文章

  • 字符串常见操作
    String的底层结构而在jdk8中,String的底层是用的字符数组。jdk9里面做了更改,节约String占用的内存。一个char占用两个字节,而程序中绝大多数String只有Latin-1字符......
  • 字符串部分知识整理
    引入:字符串最长公共前缀(LongestCommonPrefix,LCP)普通求法利用hash。设需要求\(S,T\)字符串的LCP,则可以二分长度\(len\),求一个最大的\(len\)满足\(hash(S_1\sim......
  • Rust从入门到精通08-字符串
    Rust字符串相对于其它语言有点复杂,主要是跟所有权有关。Rust字符串涉及两种类型:&str和String1、&str-字面量str是Rust的内置类型,&str是str的借用。可以理解为字符......
  • 字符串分隔
    #include<iostream>#include<string>#include<cstdlib>usingnamespacestd;boolfindName(intsubindex,stringsubstring,string*name){ subindex=substring.f......
  • C++之字符串分割案例---数据分析-03
    stringdata="我叫李宇博,我今年13岁,我家住在不知道,今天是星期天," "我喜欢吃粑粑,我喜欢做打篮球,我的学校是太康三中,我的生日是1月1号," "我的语文成绩是:0分,我的......
  • 字符串匹配之Sunday算法
    简介Sunday算法是一种字符串匹配算法,相比于KMP算法,它比较简单易学。在有些时候,比如字符串很长的时候,它是比KMP要高效的。核心思想从前往后匹配,匹配失败时关注主串中......
  • 学习笔记:python字符串的处理方法
    python学习字符串处理方法1.str.lower()和str.upper()实现全大写和全小写。2.str.split()能够使字符串以一种格式分割开,并返回一个分割完成的列表。3.str.count(x)......
  • 力扣205(java)-同构字符串(简单)
    题目:给定两个字符串 s 和 t ,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。每个出现的字符都应当映射到另一......
  • 8.字符串容器string
    1.马上补充?.对于string中字母的大小写转换函数transform(str.begin(),str.end(),str.begin(),::tolower);//将str字符串中的大写转换为小写,保存在str中transform(st......
  • 代码随想录day11 ● 232.用栈实现队列 ● 225. 用队列实现栈 ● 20. 有效的括号 ●
    232.用栈实现队列1classMyQueue{2public:34//初始化入队栈和出队栈5stack<int>stIn;6stack<int>stOut;78MyQueue(){9......