c语言回文串试题,最短回文串 -- C语言

需求

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

示例 1:

输入: "aacecaaa"

输出: "aaacecaaa"

示例 2:

输入: "abcd"

输出: "dcbabcd"

思路

要找到最短的添加内容,就相当于从字符串位置0开始,查找到最长的回文串,最长回文串后面的部分称为有效后缀,我们将有效后缀反转,添加到原有字符串的最前面就可以了

代码实现

/*

* 需求

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

示例 1:

输入: "aacecaaa"

输出: "aaacecaaa"

示例 2:

输入: "abcd"

输出: "dcbabcd"

gcc shortestPalindrome.c -g -o a.exe -DDEBUG

*/

#include #include #include #include #include #ifdef DEBUG

#define LOG(fmt, args...) fprintf(stdout, fmt, ##args)

#define BREAKER(a, b, c) breaker(a, b, c)

#else

#define LOG(fmt,...)

#define BREAKER(a, b, c)

#endif

#define TRUE 1

#define FALSE 0

#define MAX(a, b) ((a) > (b) ? (a) : (b))

#define MIN(a, b) ((a) > (b) ? (b) : (a))

bool isPalindromeStr(char * head, char * tail){

bool ret = true;

while(head < tail){

if(*head != *tail){

ret = false;

break;

}

head++;

tail--;

}

return ret;

}

int longestPalindromeSubstrFromHead(char * s, char ** pdrear){

int len = 0, pdlen = 0;

char * rear = NULL;

len = strlen(s);

rear = s + len - 1;

if('\0' == *s){

*pdrear = s;

return pdlen;

}

do {

if(isPalindromeStr(s, rear)){

/*找到了从0开始最长的回文串*/

break;

}

rear--;

} while(rear != s);

*pdrear = rear;

pdlen = rear - s + 1;

return pdlen;

}

char * shortestPalindrome(char * s){

if(NULL == s){

return NULL;

}

char * rear = NULL, * pdrear = NULL;

char * substr = NULL, *p = NULL;

int pdlen = 0, len = 0, total = 0;

len = strlen(s);

if(0 == len){ /*空字符串*/

substr = (char *)malloc(1 * sizeof(char));

*substr = '\0';

goto out;

}

rear = s + len - 1;

pdlen = longestPalindromeSubstrFromHead(s, &pdrear);

total = len - pdlen + len + 1; /*后缀长度 + 原有字符串长度 + '\0' */

LOG("s = %s, pdlen = %d, pdrear = %c, total= %d\n", s, pdlen, *pdrear, total);

substr = (char *)malloc(total * sizeof(char));

if(NULL == substr){

return NULL;

}

p = substr;

while(rear != pdrear){

*p = *rear;

p++;

rear--;

}

memcpy(p, s, len);

substr[total - 1] = '\0';

LOG("substr = %s\n", substr);

out:

return substr;

}

void testshortestPalindrome(void){

printf("\n************ testshortestPalindrome ************ \n");

char * pdstr = NULL;

#if 1

int pdlen = 0;

char astr1[100] = "aacecaaa";

char * rear = NULL;

pdlen = longestPalindromeSubstrFromHead(astr1, &rear);

*(rear + 1) = '\0';

printf("The longest PalindromeSubstr From Head is \"%s\", long %d \n", astr1, pdlen);

char astr2[100] = "abcd";

rear = NULL;

pdlen = longestPalindromeSubstrFromHead(astr2, &rear);

*(rear + 1) = '\0';

printf("The longest PalindromeSubstr From Head is \"%s\" long %d \n", astr2, pdlen);

char astr3[100] = "";

rear = NULL;

pdlen = longestPalindromeSubstrFromHead(astr3, &rear);

*(rear + 1) = '\0';

printf("The longest PalindromeSubstr From Head is \"%s\" long %d \n", astr3, pdlen);

#endif

#if 1

/*testcase 1*/

char * str1 = "aacecaaa";

pdstr = shortestPalindrome(str1);

printf("The shortest pdstr is \"%s\" \n", pdstr);

if(NULL != pdstr){

free(pdstr);

pdstr = NULL;

}

/*testcase 2*/

char * str2 = "abcd";

pdstr = shortestPalindrome(str2);

printf("The shortest pdstr is \"%s\" \n", pdstr);

if(NULL != pdstr){

free(pdstr);

pdstr = NULL;

}

/*testcase 2*/

char * str3 = "";

pdstr = shortestPalindrome(str3);

printf("The shortest pdstr is \"%s\" \n", pdstr);

if(NULL != pdstr){

free(pdstr);

pdstr = NULL;

}

#endif

return;

}

int main(int argc, char ** argv){

testshortestPalindrome();

}

代码编译

gcc shortestPalindrome.c -g -o a.exe -DDEBUG

调试输出

************ testshortestPalindrome ************

The longest PalindromeSubstr From Head is "aacecaa", long 7

The longest PalindromeSubstr From Head is "a" long 1

The longest PalindromeSubstr From Head is "" long 0

s = aacecaaa, pdlen = 7, pdrear = a, total= 10

substr = aaacecaaa

The shortest pdstr is "aaacecaaa"

s = abcd, pdlen = 1, pdrear = a, total= 8

substr = dcbabcd

The shortest pdstr is "dcbabcd"

The shortest pdstr is ""

682098b957aef7a6c4a7b4f1bafd38f2.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值