• 最长回文串


    先帖个代码

    // project1.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include<string.h>
    
    #define LENGTH 1000
    
    //最大回文串,动态规划法:对暴力搜索的改进
    //暴力搜索O(N^2)个子串,每次O(N),总开销O(N^3)
    //通过动态规划法复杂度可以降到O(N^2)
    int LPS_dp(char *str){
        int len=strlen(str);
        bool dp[LENGTH][LENGTH];//dp[i][j]记录子串[i..j]是否回文
        int maxlen=0,beg_pos=0;
        for(int i=0;i<len;i++){
            dp[i][i]=1;//单字符回文
            if(i>0 && str[i-1]==str[i])
                dp[i-1][i]=1;//双字符回文.dp[a][b]表示str[a..b]的子串是否是回文串,如果是,标记1
        }
        for(int length=2;length<len;length++){//回文串长
            for(int begin=0;begin<len-length;begin++){//起始位置
                int end=begin+length;
                if(str[begin]==str[end] && dp[begin+1][end-1]==1){
                    dp[begin][end]=1;
                    if(end-begin+1>maxlen){
                        maxlen=end-begin+1;
                        beg_pos=begin;
                    }
                }
            }
        }
        return maxlen;
    }
    
    //O(N^2)复杂度
    int LPS_two(char *str){
        int LPS_rb[LENGTH];//i为中心的回文子串右边界下标right border
        char new_str[LENGTH];//保存对str处理后的数组
        memset(new_str,0,sizeof(char)*LENGTH);
        int maxlen=0;
    
        new_str[0]='$';
        new_str[1]='#';
        //为什么要对原数组进行处理呢?
        //例如,原本aba变成$a#b#a#,这样不管是单字符回文还是双字符回文,都可以用new_str[i-k] == new_str[i+k]进行比较
        for(char *p=str,i=2;*p;p++){//处理数组
            new_str[i]=*p;
            new_str[i+1]='#';
            i+=2;
        }
    
        int len=strlen(new_str);
        for(int i=1;i<len;i++){//计算LPS_rb数组
            LPS_rb[i]=1;//初始化
            while(new_str[i-LPS_rb[i]]==new_str[i+LPS_rb[i]])
                LPS_rb[i]++;
            if(LPS_rb[i]-1>maxlen)
                maxlen=LPS_rb[i]-1;
        }
        return maxlen;
    }
    
    //对LPS_two的优化,复杂度降到O(N)
    int LPS_two_opt(char *str){
        int LPS_rb[LENGTH];//i为中心的回文子串右边界下标right border
        char new_str[LENGTH];//保存对str处理后的数组
        memset(new_str,0,sizeof(char)*LENGTH);
      //增加了这几个字段
    //maxlen为LPS的长度,max_center中心位置,max_rb为右边界 int maxlen=0,max_center=0,max_rb=0; new_str[0]='$'; new_str[1]='#'; //为什么要对原数组进行处理呢? //例如,原本aba变成$a#b#a# for(char *p=str,i=2;*p;p++){//处理数组 new_str[i]=*p; new_str[i+1]='#'; i+=2; } int len=strlen(new_str); for(int i=1;i<len;i++){//计算LPS_rb数组
    //本算法的核心在此。这个if语句将复杂度降到O(N) if(max_rb>i) //max_rb为当前最大串的右边界 //如果最大串的右边界在i之后
           //LPS_rb[i]表示以i为中心的回文串的右边界
           //如果max_rb>i,则说明在以max_center为中心对称的左侧也有个字符即str[2*max_center -i] = str[i]
    //于是可以利用已计算好的str[2*max_center-i]的LPS_rb[2*max_center-i]来计算LPS_rb[i],于是LPS_rb[i]至少大于等于 min(LPS_rb[2*max_center-i],(max_rb-i)) //2*max_center-i为i关于max_center的对称点 LPS_rb[i] = (LPS_rb[2*max_center-i]<(max_rb-i)) ? LPS_rb[2*max_center-i]:(max_rb-i); else LPS_rb[i]=1;     //从min(LPS_rb[2*max_center-i],(max_rb-i))开始增加,这样如此便节省了一些次的循环,因此会降低算法复杂度   while(new_str[i-LPS_rb[i]]==new_str[i+LPS_rb[i]]) LPS_rb[i]++; if(LPS_rb[i]-1>maxlen){ maxlen=LPS_rb[i]-1; max_center=i; max_rb=i+maxlen; } } return maxlen; } int _tmain(int argc, _TCHAR* argv[]) { char str1[LENGTH]="abbaeaabccbaeeaee"; char str2[LENGTH]="aaaaaaaaa"; char str3[LENGTH]="abababababab"; printf("LPS:%d ",LPS_dp(str1));printf("LPS:%d ",LPS_dp(str2));printf("LPS:%d ",LPS_dp(str3)); printf("LPS:%d ",LPS_two(str1));printf("LPS:%d ",LPS_two(str2));printf("LPS:%d ",LPS_two(str3)); printf("LPS:%d ",LPS_two_opt(str1));printf("LPS:%d ",LPS_two_opt(str2));printf("LPS:%d ",LPS_two_opt(str3)); return 0; }



  • 相关阅读:
    将本地文件夹添加到Git仓库
    flex调用Webservice(一)
    经典的sql
    打印相关
    reporting services订阅
    关于TabIndex
    试题(一)
    试试用手机
    2010.07.13_19:30
    基础知识
  • 原文地址:https://www.cnblogs.com/abc123456789/p/3433431.html
Copyright © 2020-2023  润新知