c语言回文字符串判断函数的奇偶性,leetcode-7:回文串问题

回文串问题

解释一下为什么会记录刷题过程。记得研一为了算法课刷题,曾经在本子中记录过思路和代码。这些算法思想,平常也没机会使用,长时间不用,忘得比较快,再加上本子不易保存和现在电子阅读的普及,所以就导致复习不好复习,还得从头再来,所以这次刷题就记录下来,发在csdn和知乎,以便随时观看。

最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

思路: 最长回文子串问题的解决方法有常见的O ( n 2 ) O\left(n^{2}\right)O(n2),还有神奇的O ( n ) O\left(n\right)O(n),被称为马拉车算法。对于O ( n 2 ) O\left(n^{2}\right)O(n2)算法,是考虑到回文串的对称性,每次循环选择一个中心,左右扩展,直到左右字符不再相等。考虑到字符串长度的奇偶性,为了全面寻找最长回文串,需要从一个字符开始扩展,或者从两个字符间开始扩建,有2n-1个中心点。

class Solution {

public:

string longestPalindrome(string s) {

int len = s.length();

if(len==0) return "";

int left=0, right=0;

for(int i=0;ilen_2 ? len_1 : len_2;

if((right - left) < len){

left = i - (len - 1) / 2;

right = i + len / 2;

}

}

return s.substr(left, (right - left + 1));

}

int expand(string s, int left, int right){

while(left>=0&&right

马拉车算法(Manacher’s Algorithm)

马拉车算法将时间复杂度降到了O ( n ) O\left(n\right)O(n),但是空间复杂度为O ( n ) O\left(n\right)O(n)。上述的中心扩展法的空间复杂度为O ( 1 ) O\left(1\right)O(1),用空间换取时间。

中心扩展的时候需要考虑到字符串奇偶性,假设字符串长度为n nn,通过加入n + 1 n+1n+1个分隔符使得字符串长度为奇数2 n + 1 2n+12n+1,将“babad”处理成“#b#a#b#a#d#"。

设置目前回文串的对称中心点为Center,回文半径长度为Radius,右边到达最远为Right=Center+Radius,当前点为i ii,i ii关于Center的对称点为i _ m i r r o r = 2 ∗ C e n t e r − i i\_mirror = 2 *Center - ii_mirror=2∗Center−i。记录每个点回文字符串半径的矩阵为P PP。

我们需要根据i和Right的大小来计算P [ i _ m i r r o r ] P[i\_mirror]P[i_mirror]。

当i < R i g h t i < Righti = R i + P[i\_mirror] >= Ri+P[i_mirror]>=R,那么可以根据回文串对称性得到P [ i ] = P [ i _ m i r r o r ] P[i] = P[i\_mirror]P[i]=P[i_mirror];否则,超越界限,所以需要取m i n ( P [ i _ m i r r o r ] , R − i ) min(P[i\_mirror], R-i)min(P[i_mirror],R−i),然后再左右扩展

如果i > R i > Ri>R,此时镜像预测不起作用,P [ i ] = 0 P[i] = 0P[i]=0,需左右扩展。

class Solution {

public:

string pre_process(string s){

int len = s.length();

len = 2 * len + 1;

string str="";

for(int i=0;iP(len, 0);

int c = 0, r = 0;

int max_length = INT_MIN;

int max_index = 0;

for(int i=0;ii){

P[i] = min(r-i, P[i_mirror]);

}

while(((i+P[i])=0)&&str[i+P[i]]==str[i-P[i]]){

P[i]++;

}

if((i+P[i]) > r){

c = i;

r = i+P[i];

}

if(max_length < P[i]){

max_index= i;

max_length = P[i];

}

}

return s.substr((max_index - max_length + 1)/2, max_length-1);

}

};

回文子串

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

思路: 简单暴力,我们搜索每一个中心点。假设字符串长度为n nn,按照扩展算法的描述,有2 ∗ n + 1 2*n+12∗n+1中心,对每一中心进行扩展,如果是回文串,则记录下来。

class Solution {

public:

int countSubstrings(string s) {

int len = s.length();

len = len*2-1;

int left=0,right=0;

int num = 0;

for(int i=0;i=0&&right

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值