目录1,判断字符串为回文列2,寻找字符串中有几个回文部分列1,暴力列举2、中心扩张法3、动态计划4、Manacher (慈爱乌冬面车)算法3、回文部分列的最大长度
一.判断字符串为回文字符串
回文串:字符串翻转后与原始字符串相同。 例如aba
判断代码如下,考虑从头尾开始依次比较,如果全部相同,则意味着是回文串
时间复杂度为o(n ),空间复杂度为o ) )1)
//字符串i-j为回文字符串boolispalindromic(strings,int i,int j ) (while ) Ij ) ) if ) s[I]!=s[j--]{returnfalse; } }返回真; )二、查找字符串中有多少个回文子串(1、暴力枚举直接遍历整个字符串
时间复杂度为o(n3 ),空间复杂度为o )1)
intcountsubstrings(strings ) {int count=0; int len=s.size (; for(intI=0; i len; I ) for(intj=I; j len; j () if ) ispalindromic(s,I,j )==true ) {count; } } }返回计数; ) 2、因为中心扩张法的回文列是对称的,所以如果在回文列的头尾添加相同的字符,则得到的新字符串一定是回文列。
这样扫描时,从一个中心点向两侧扩展,判断左右边是否相等即可。 这样就不需要每次都从头开始遍历
时间复杂度为o(n2 ),空间复杂度为o )1)
intcountsubstrings(strings ) {int len=s.size,count=0; if(len==0) { return 0; }for(intI=0; i len; I ) ) /回文串有奇数和偶数的长度,中心点的长度为1和2个count=expandaroundcenter(s,I,I ); 从//1字符扩展count=expandaroundcenter(s,I,i 1 );//从两个字符之间扩展(} return count; }intexpandaroundcenter(strings,int left,int right ) int left,r=right,count=0; int len=s.size (; while(L=0rlens[L]==s[R] ) L--; r; 出局; }返回计数; }代码优化,看看上面的代码。 在最后一次扫描中,i 1超出了数组的范围,所以该次没有被扫描
因此,得知扫描中心点的数量为2 * len - 1,分别为len个1个文字和len - 1个2个文字。
举一个例子,有ABA:a、ab、b、ba、a这5个中心点
intcountsubstrings(strings ) {int n=s.size ),count=0; //因为要进行遍历,所以需要将中心点for(intI=0; i 2 * n - 1; I ) (/单个中心点l和r重合的int l=i/2,r=i/2 i % 2; wile(L=0rns[L]==s[R] ) { --l; r; 出局; } }返回计数; } 3、在确认动态计划开头字符相等的情况下,如果中间字符串是回文串,则可以确认当前字符串是回文串。
这样,可以用二维数组记录字符串是否为回文列,并可以像填写表那样传递各个字符
字符串是否为回文字符串。
时间复杂度为o(n2 ),空间复杂度为o ) n2 )
intcountsubstrings(strings ) {int count=0; int len=s.length; bool **dp=new bool*[len]; for(intI=0; i len; I ) {dp[i]=new bool[len]; for(intj=0; j len; j({DP[I][j]=false; }for(intj=0; j len; j ) for(intI=0; i=j; I ) {
if (i == j) // 单个字符{ dp[i][j] = true;count++;} else if (j - i == 1 && s[i] == s[j]) // 两个字符 { dp[i][j] = true;count++;} else if (j - i > 1 && s[i] == s[j] && dp[i + 1][j - 1]) // 多于两个字符{ dp[i][j] = true;count++;}}}return count;}; 4、Manacher(慈祥的乌冬面车)算法慈祥的乌冬面车算法很巧妙,利用了回文串对称的特性尽最大的努力去减少中心扩展的比较次数,
不会无脑的去比较而是把前面的状态记录下来加以利用。
因为慈祥的乌冬面车算法的最大回文右端点r_max只会变大不会变小,所以遍历的次数不会超过过n
时间复杂度为O(n),空间复杂度O(n)
上面几种算法都遍历的所有子串,只需要在每次确认字串时记录当前子串长度,找出最大的子串即可。