zoukankan      html  css  js  c++  java
  • 最长回文子串

    1、问题描述

    给定一个字符串 s,找到 s 中最长的回文子串。

    2、算法分析

    大多数问题都可以用暴力法解决。暴力法将选出所有子字符串可能的开始和结束位置,并检验它是不是回文。

    • 时间复杂度:O(n3),假设 n 是输入字符串的长度,则 (n * (n−1))/2​ 为此类子字符串(不包括字符本身是回文的一般解法)的总数。因为验证每个子字符串需要 O(n) 的时间,所以运行时间复杂度是 O(n3)。

    • 空间复杂度:O(1)。 

    为了改进暴力法,我们首先观察如何避免在验证回文时进行不必要的重复计算。考虑 "ababa" 这个示例。如果我们已经知道 "bab" 是回文,那么很明显,"ababa" 一定是回文,因为它的左首字母和右尾字母是相同的。

    我们给出 P(i,j) 的定义如下:

    如果子串 Si...Sj ​是回文子串   p(i, j) = true
    
    其他情况                   p(i, j) = false
    

    因此:

    P(i, j) = ( P(i+1, j-1) and Si​ == Sj​)
    

    基本示例如下:

    P(i, i) = true
    
    P(i, i+1) = (Si ​== Si+1​)
    

    这产生了一个直观的动态规划解法,我们首先初始化一字母和二字母的回文,然后找到所有三字母回文,并依此类推…

    3、复杂度分析

    • 时间复杂度:O(n2),这里给出我们的运行时间复杂度为 O(n2)。

    • 空间复杂度:O(n2),该方法使用 O(n2) 的空间来存储表。

    4、代码实现

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char * longestPalindrome(char* s)
    {
        if (s == NULL || strlen(s) < 1) {
            return "";
        }
        int n = (int)strlen(s);
        
        // 初始化二维数组
        int matrix[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j< n; j++)
                matrix[i][j] = 0;
        
        int left  = 0;
        int right = 0;
        
        // i 从倒数第二个开始,从右往左。标识子串的起始位置
        for (int i = n - 2; i >= 0; i--) {
            
            matrix[i][i] = 1;
            
            // j 从 i 的下一位开始,从左往右。标识子串的结束位置
            for (int j = i + 1; j < n; j++) {
                
                // ①、s[i] == s[j]     ②、小于或等于 3 个字符     ③、内缩一位是回文子串
                matrix[i][j] = (s[i] == s[j] && (j - i < 3 || matrix[i+1][j-1]));
                
                // 获得最长的子串位置
                if(matrix[i][j] && right - left < j - i) {
                    left  = i;
                    right = j;
                }
                
                for (int m = 0; m < n; m++) {
                    for (int k = 0; k < n; k++)
                        printf("%d   ", matrix[m][k]);
                    printf("
    
    ");
                }
            }
        }
        
        char* sub = (char *)malloc(sizeof(char) * (right - left + 1));
        int i = 0;
        for (; i < right - left + 1; i++) {
            sub[i] = s[left + i];  //strncpy(sub, s+left, right+1);
        }
        sub[i] = '';
        
        return sub;
    }
    
    int main()
    {
        printf("%s", longestPalindrome("aaabaaaa"));
        
        return 0;
    }
    

    关键代码:

    matrix[i][j] = (s[i] == s[j] && (j - i < 3 || matrix[i+1][j-1])); 以及 i 和 j 的取值方向

  • 相关阅读:
    nullnullConnecting with WiFi Direct 与WiFi直接连接
    nullnullUsing WiFi Direct for Service Discovery 直接使用WiFi服务发现
    nullnullSetting Up the Loader 设置装载机
    nullnullDefining and Launching the Query 定义和启动查询
    nullnullHandling the Results 处理结果
    装置输出喷泉装置(贪心问题)
    数据状态什么是事务?
    停止方法iOS CGD 任务开始与结束
    盘文件云存储——金山快盘
    函数标识符解决jQuery与其他库冲突的方法
  • 原文地址:https://www.cnblogs.com/dins/p/longest-text-substring.html
Copyright © 2011-2022 走看看