所谓回文串就是从前面读和从后面读完全一样的字符串。根据字符数量分为两类:
-奇数个:中间数字只有一个 aba
-偶数个:中间数字有两个 abba
这个函数的前提是l和r满足这样的关系:
l==r 或者r=l+1
string palindrome(string &s, int l, int r){
while(l>=0&&r<s.size()&&s[l]==s[r]){
l--;
r++;
}
return str.substr(l+1,r-l-1);
}
思路
在长度为 N 的字符串中,可能的回文串中心位置有 2N-1 个:字母,或两个字母中间。
从每一个回文串中心开始统计回文串数量。回文区间 [a, b] 表示 S[a], S[a+1], …, S[b] 是回文串,根据回文串定义可知 [a+1, b-1] 也是回文区间。
算法
对于每个可能的回文串中心位置,尽可能扩大它的回文区间 [left, right]。当 left >= 0 and right < N and S[left] == S[right] 时,扩大区间。此时回文区间表示的回文串为 S[left], S[left+1], …, S[right]。
代码:
for(int i=0;i<2*n-1;i++){
int left=i/2;
int right=i%2;
}
通过以上代码就枚举了所有的中心元素情况。包含一个中心和两个中心的情况。然后扩展即可。
思路
马拉车算法可以在线性时间内找出以任何位置为中心的最大回文串。
算法
假设一个回文串中心为 center,该中心对应的最大回文串右边界为 right。存在一个 i 为当前回文串中心,满足 i > center,那么也存在一个 j 与 i 关于 center 对称,可以根据 Z[i] 快速计算出 Z[j]。
当 i < right 时,找出 i 关于 center 的对称点 j = 2 * center - i。此时以 i 为中心,半径为 right - i 的区间内存在的最大回文串的半径 Z[i] 等于 Z[j]。
例如,对于字符串 A = ‘@#A#B#A#A#B#A#$’,当 center = 7, right = 13, i = 10 时,center 为两个字母 A 中间的 #,最大回文串右边界为最后一个 #,i 是最后一个 B,j 是第一个 B。
在 [center - (right - center), right] 中,区间中心为 center,右边界为 right,i 和 j 关于 center 对称,且 Z[j] = 3,可以快速计算出 Z[i] = min(right - i, Z[j]) = 3。
在 while 循环中,只有当 Z[i] 超过 right - i 时,才需要逐个比较字符。这种情况下,Z[i] 每增加 1,right 也会增加 1,且最多能够增加 2*N+2 次。因此这个过程是线性的。
最后,对 Z 中每一项 v 计算 (v+1) / 2,然后求和。假设给定最大回文串中心为 C,半径为 R,那么以 C 为中心,半径为 R-1, R-2, …, 0 的子串也都是回文串。例如 abcdedcba 是以 e 为中心,半径为 4 的回文串,那么 e,ded,cdedc,bcdedcb 和 abcdedcba 也都是回文串。
除以 2 是因为实际回文串的半径为 v 的一半。例如回文串 a#b#c#d#e#d#c#b#a 的半径为实际原回文串半径的 2 倍。
def countSubstrings(self, S):
def manachers(S):
A = '@#' + '#'.join(S) + '#$'
Z = [0] * len(A)
center = right = 0
for i in xrange(1, len(A) - 1):
if i < right:
Z[i] = min(right - i, Z[2 * center - i])
while A[i + Z[i] + 1] == A[i - Z[i] - 1]:
Z[i] += 1
if i + Z[i] > right:
center, right = i, i + Z[i]
return Z
return sum((v+1)/2 for v in manachers(S))
对链表后半部分进行翻转。然后顺序比较即可。翻转可以在原地操作。
**思路:**快慢指针找到链表的中间元素。根据fast是否为空确定链表长度是奇数还是偶数。如果是奇数,slow还得往后移动一个。
然后对slow开始的链表进行翻转。
翻转链表
ListNode* reverse(ListNode *node){
ListNode *pre=NULL,*cur=node;
while(cur){
ListNode *next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
return pre;
}