回文子串个数

2019-01-19  本文已影响0人  IceFrozen

注意子串和子序列的区别
子串:必须连续
子序列:可以不连续
两者都可以包含字符串本身

解法一:暴力求解
#include <stdio.h>
#include <string.h>
#include <malloc.h>

_Bool palindrome (char *str) {    //判断一个字符串是否回文
    int tag = 1;
    for (int i = 0, len = strlen(str); i <= len / 2; i++) {
        if (str[i] != str[len - i - 1])
            tag = 0;
    }
    if (tag)
        return 1;
    else 
        return 0;
}

int subPalindromeNum (char *str) {    //计算回文子串个数
    int len = strlen(str);
    int count = 0;    //记录回文子串个数
    for (int i = 0; i < len; i++)    //遍历每一个子串
        for (int j = i; j < len; j++) {
            int n = 0;
            char *temp = (char *) malloc (sizeof(char) * (j - i + 2));    //拷贝遍历过程中的每一个字符串
            for (int k = i; k <= j; k++)
                temp[n++] = str[k];
            temp[n] = '\0';
            if (palindrome(temp))
                count++;
            free(temp);
        }
    return count;
}

int main() {
    for (char str[1000]; ~scanf("%s", &str);)
        printf("%d\n", subPalindromeNum(str));
    return 0;
}
解法二:动态规划
#include <stdio.h>
#include <malloc.h>
#include <string.h>

int subPlalindromeNum (char *str, int len) {
    if (len == 0)
        return 0;
    int count = 0;    //记录结果
    int **dp = (int **) malloc (sizeof(int *) * len);    //动态分配二维 dp 数组并初始化为 0
    for (int i = 0; i < len; i++) {
        dp[i] = (int *) malloc (sizeof(int) * len);
        for (int j = 0; j < len; j++) {
            dp[i][j] = 0;
        }
    }
    for (int i = 0; i < len; i++) {    //第二个循环在遍历第一个循环已经遍历过的字符,保证了 dp 数组的有效性
        dp[i][i] = 1;
        count++;
        for (int j = i - 1; j >= 0; j--)
            if (str[i] == str[j])    //判断首尾是否相等
                if (i - 1 == j || dp[i - 1][j + 1]) {    //首尾连续或者去掉首尾是回文,则计数
                    dp[i][j] = 1;
                    count ++;
                }
    }
    free(dp);
    return count;
}

int main() {
    for (char str[10000]; ~scanf("%s", str);)
        printf("%d\n", subPlalindromeNum(str, strlen(str)));
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读