【编程题目】对称子字符串的最大长度 ★

73.对称字符串的最大长度(字符串)。
题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。
比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出 4。

虽然知道会有简单的方法,可脑子就是转不动了,只好用最常见的,对所有可能的字符串判断是否为对称的。再输出最大长度 O(N3)

/*
73.对称字符串的最大长度(字符串)。
题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。
比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出 4。
*/

#include <stdio.h>
#include <string.h>

bool issymmetry(char * in, int len) //判断字符串是否对称
{
    int i, j;
    for(i = 0, j = len - 1; i < j ; i++, j--)
    {
        if(in[i] != in[j])
        {
            return false;
        }
    }
    return true;
}

int maxSubSymLen(char * in, int len)
{
    int nlen;
    for(nlen = len; nlen >= 1; nlen--) //按长度循环
    {
        if(nlen == 1)
        {
            return 1;
        }
        else
        {
            int i;
            for(i = 0; i <= len - nlen; i++) //首字母位置循环
            {
                if(issymmetry(in + i, nlen))
                {
                    for(int j = i; j < i + nlen; j++)
                    {
                        printf("%c ", in[j]);
                    }
                    return nlen;
                }
            }
        }
    }
}

int main()
{
    char a[40] = "asdgjoalsgjeslhfelgjdjglejf";
    int ans = maxSubSymLen(a, strlen(a));
    return 0;
}

网上O(N2)解法是 长度从小向大循环

http://blog.163.com/[email protected]/blog/static/1113522592011912103756405/

如果我们换一种思路,我们从里向外来判断。也就是我们先判断子字符串A是不是对称的。如果A不是对称的,那么向该子字符串两端各延长一个字符得到的字符串肯定不是对称的。如果A对称,那么我们只需要判断A两端延长的一个字符是不是相等的,如果相等,则延长后的字符串是对称的。因此在知道A是否对称之后,只需要O(1)的时间就能知道aAa是不是对称的。

/*
取得所有对称子串的最大长度
时间复杂度: O(n^2)
*/

int GetLongestSymmetricalLength(char* pString)
{
    if(pString == NULL)
        return 0;
    int symmeticalLength = 1;
    char* pChar = pString;
    while(*pChar != ‘\0‘)
    {
        // Substrings with odd length
        char* left = pChar - 1;
        char* right = pChar + 1;
        while(left >= pString && *right != ‘\0‘ && *left == *right)
        {
            left--;
            right++;
        }
        int newLength = right - left - 1;    //退出while循环时,*left != *right
        if(newLength > symmeticalLength)
            symmeticalLength = newLength; 

        // Substrings with even length
        left = pChar;
        right = pChar + 1;
        while(left >= pString && *right != ‘\0‘ && *left == *right)
        {
            left--;
            right++;

        }
        newLength = right - left - 1;        //退出while循环时,*left != *right
        if(newLength > symmeticalLength)
            symmeticalLength = newLength;
        pChar++;
    }
    return symmeticalLength;
}

居然还有O(N)的算法!!

http://blog.csdn.net/hackbuteer1/article/details/6686263

经常有一些题目围绕回文子串进行讨论,比如 HDOJ_3068_最长回文,求最长回文子串的长度。朴素算法是依次以每一个字符为中心向两侧进行扩展,显然这个复杂度是O(N^2)的,关于字符串的题目常用的算法有KMP、后缀数组、AC自动机,这道题目利用扩展KMP可以解答,其时间复杂度也很快O(N*logN)。但是,今天笔者介绍一个专门针对回文子串的算法,其时间复杂度为O(n),这就是manacher算法。
大家都知道,求回文串时需要判断其奇偶性,也就是求aba和abba的算法略有差距。然而,这个算法做了一个简单的处理,很巧妙地把奇数长度回文串与偶数长度回文串统一考虑,也就是在每个相邻的字符之间插入一个分隔符,串的首尾也要加,当然这个分隔符不能再原串中出现,一般可以用‘#’或者‘$’等字符。例如:
原串:abaab
新串:#a#b#a#a#b#
这样一来,原来的奇数长度回文串还是奇数长度,偶数长度的也变成以‘#’为中心的奇数回文串了。
接下来就是算法的中心思想,用一个辅助数组P记录以每个字符为中心的最长回文半径,也就是P[i]记录以Str[i]字符为中心的最长回文串半径。P[i]最小为1,此时回文串为Str[i]本身。
我们可以对上述例子写出其P数组,如下
新串:
# a # b # a # a # b #
P[]  :  1 2 1 4 1 2 5 2 1 2
1
我们可以证明P[i]-1就是以Str[i]为中心的回文串在原串当中的长度。
证明:
1、显然L=2*P[i]-1即为新串中以Str[i]为中心最长回文串长度。
2、以Str[i]为中心的回文串一定是以#开头和结尾的,例如“#b#b#”或“#b#a#b#”所以L减去最前或者最后的‘#’字符就是原串中长度的二倍,即原串长度为(L-1)/2,化简的P[i]-1。得证。
依次从前往后求得P数组就可以了,这里用到了DP(动态规划)的思想,也就是求P[i]的时候,前面的P[]值已经得到了,我们利用回文串的特殊性质可以进行一个大大的优化。

#include <stdio.h>

#define M 110010

char b[M],a[M<<1];
int p[M<<1];

int Min(int a,int b)
{
    return a<b?a:b;
}

int main(void)
{
    int i,n,id,MaxL,MaxId;
    while(scanf("%s",&b[1])!=EOF)
    {
        MaxL=MaxId=0;
        for(i=1;b[i]!=‘\0‘;i++)
        {
            a[(i<<1)]=b[i];
            a[(i<<1)+1]=‘#‘;
        }
        a[0]=‘?‘;a[1]=‘#‘;
        n=(i<<1)+2;a[n]=0;
        MaxId=MaxL=0;
        for(i=1;i<n;i++)
        {
            if(MaxId>i)
            {
                p[i]=Min(p[2*id-i],MaxId-i);
            }
            else
            {
                p[i]=1;
            }
            while(a[i+p[i]]==a[i-p[i]])
            {
                p[i]++;
            }
            if(p[i]+i>MaxId)
            {
                MaxId=p[i]+i;
                id=i;
            }
            if(p[i]>MaxL)
            {
                MaxL=p[i];
            }
        }
        printf("%d\n",MaxL-1);
    }
    return 0;
}

【编程题目】对称子字符串的最大长度 ★

时间: 2024-11-03 05:44:01

【编程题目】对称子字符串的最大长度 ★的相关文章

46. 对称子字符串的最大长度(ToDo)

题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度.比如输入字符串"google",由于该字符串里最长的对称子字符串是"goog",因此输出4. 分析:可能很多人都写过判断一个字符串是不是对称的函数,这个题目可以看成是该函数的加强版. 引子:判断字符串是否对称 要判断一个字符串是不是对称的,不是一件很难的事情.我们可以先得到字符串首尾两个字符,判断是不是相等.如果不相等,那该字符串肯定不是对称的.否则我们接着判断里面的两个字符是不是相等,以此类推.基于这个

输入一个字符串,输出该字符串中对称的子字符串的最大长度。

public class LongestSymmtricalLength2 { /* * Q75题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度. * 比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4. */ public static void main(String[] args) { String[] strs = { "a","google", "elgoog", "agol

【编程题目】在一个字符串中找到第一个只出现一次的字符。如输入 abaccdeff,则输出 b。

第 17 题(字符串):题目:在一个字符串中找到第一个只出现一次的字符.如输入 abaccdeff,则输出 b. 思路:此题非常容易. 最开始是想开辟一块空间存储每个字符出现的次数. 但转念一想,似乎没有必要. 对每一个字符,都依次和后面的比较,若出现了两次,则检查下一个字符,遇到只出现一次的,直接输出就好了. /* 第 17 题(字符串): 题目:在一个字符串中找到第一个只出现一次的字符.如输入 abaccdeff,则输出 b. 分析:这道题是 2006 年 google 的一道笔试题. */

OJ——华为编程题目:输入字符串括号是否匹配

package t0815; /* * 华为编程题目:输入字符串括号是否匹配 * 若都匹配输出为0,否则为1 * 样例输入:Terminal user [name | number (1)] * 样例输出:0 * Java版本 */ /* * 个人总结: * (1)语法上Java的输入Scanner使用 * (2)char[] arr=mxf.toCharArray()的使用,将输入的字符串转成字符数组:这样就可以一个 * 一个的遍历 * (3)算法上,这里使用了经典的入栈和出栈的思想 * */

【编程题目】在字符串中删除特定的字符

63.在字符串中删除特定的字符(字符串).题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符.例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”. 我的思路:先扫描第一个字符串,判断是否是第二的字符串的字符,是则跳过,记录跳过多少个,后面的不被删除的就前移. /* 63.在字符串中删除特定的字符(字符串). 题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符. 例如,输入”They are s

【目录】编程题目

编程题目 如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1) 一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数.☆ 请修改 append 函数,利用这个函数实现两个非降序链表的并集 一串首尾相连的珠子(m 个),有 N 种颜色(N<=10),取出其中一段,要求包含所有 N 中颜色,并使长度最短. 求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边, 有向图不再连通 有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前

字符串匹配算法一:查找子字符串

[题目] 就是给一个很长的字符串str 还有一个字符集比如{a,b,c} 找出str里包含{a,b,c}的最短子串.要求O(n). [例子] 字符集是a,b,c,字符串是abdcaabcx,则最短子串为abc. [分析] 有题意可知,满足要求的字符串只需要包括字符集中的所有字符,并没有顺序要求 当然最容易想到的是做一个字符匹配的过程,但题目要求查找次数为O(n),在思考了几种解决方法后,觉得下面的方案能够达到要求,虽然需要一些额外的空间. 下面我给出自己的解决方案,难免有遗漏的地方,如果路过的朋

【编程题目】字符串的排列(字符串)★

53.字符串的排列(字符串).题目:输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串 abc,则输出由字符 a.b.c 所能排列出来的所有字符串abc.acb.bac.bca.cab 和 cba. 这道题花了我一天,要好好总结! 思路:这道题目感觉有些难,主要是字符串中的字符可能会有重复.我的想法是把一共有多少种字符和每种字符出现的次数统计出来,每个位置对这些字符变量,下一个位置的可用字符减小,再遍历. /* 53.字符串的排列(字符串). 题目:输入一个字符串,打印出该字符串中字

【编程题目】左旋转字符串 ☆

26.左旋转字符串(字符串)题目:定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部.如把字符串 abcdef 左旋转 2 位得到字符串 cdefab.请实现字符串左旋转的函数.要求时间对长度为 n 的字符串操作的复杂度为 O(n),辅助内存为 O(1). 思路: 设字符串为 abcdefg 要左旋两个, $$表示操作范围,|表示要旋转的轴线,将操作范围分为两个部分.每次把范围小的部分与范围大的部分的靠近|的位置交换.范围相同则直接交换. 1. $ab|cdefg$ 2