将一个很长的字符串,分割成一段一段的子字符串,子字符串都是回文字符串。有回文字符串就输出最长的,没有回文就输出一个一个的字符。
例如:
habbafgh
例如:
habbafgh
输出h,abba,f,g,h。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10001
int len, p[2 * MAX];
char str[2 * MAX], newstr[2 * MAX];
void change() {
int i;
newstr[0] = '@';
newstr[1] = '#';
for (i = 0; i < len; i++) {
newstr[2 * i + 2] = str[i];
newstr[2 * i + 3] = '#';
}
len = 2 * len + 2;
newstr[2 * len + 2] = '\0';
return;
}
void Manacher() {
/*maxid最右下标边界, ans最长回文长度, id最右边界的回文中心下标*/
int i, j, id, maxid = 0;
for (i = 0; i < len; i++) {
/*maxid > i,表明i元素出现在回文范围内
*取最小,为maxid-i时超出最右,反之包含
*maxid<=i,未出现回文,默认1*/
p[i] = maxid > i ?
p[2 * id - i] > maxid - i ? maxid - i : p[2 * id - i]:0;
/*输出字符串是根据'\0'来判断是否结束的,不会管你数组是大小,
* 就是因为这样,才有可能造成越界以后读到别人的内存,一般的内存没关系,
* 但要是恰好读到操作系统的,就会报错了*/
/*探索该下标结点的回文长度*/
while (newstr[i + 1 + p[i]] == newstr[i - 1 - p[i]]) {
p[i]++;
}
//记录最大边界,最大回文点下标
if (p[i] + i > maxid) {
maxid = p[i] + i;
id = i;
}
}
//记录最大回文长度
int maxLen = 0;
//最长回文中心下标
int centerIndex = 0;
for (i = 1; i < len; i++) {
if (p[i] > maxLen) {
maxLen = p[i];
centerIndex = i;
}
}
//无回文
if (maxLen == 1) {
for (i = 0; i < strlen(str); i++) {
if (i != 0) {
printf(",");
}
printf("%3c", str[i]);
}
} else {
//存在回文
int start = (centerIndex - 1 - maxLen) / 2;
for (i = 0; i < start; i++) {
if (i != 0) {
printf(",");
}
printf("%3c", str[i]);
if (i == start - 1) {
printf(",");
}
}
for (i = (centerIndex - 1 - maxLen) / 2, j = 0; j < maxLen; i++, j++) {
printf("%3c", str[i]);
}
for (; i < strlen(str); i++) {
printf(",");
printf("%3c", str[i]);
}
}
str[j] = '\0';
return;
}
int main(void) {
strcpy(str, "habbafgh");
len = strlen(str);
change();
Manacher();
// puts(str);
return EXIT_SUCCESS;
}
382

被折叠的 条评论
为什么被折叠?



