C语言求最长回文子串大小(On)

最长回文子串大小

#输入一段字符串得到最长回文字串的大小

输入:asdffdaaa

输出:4

输入:abs

输出:1

这是一种时间复杂度为O(n)的算法,它利用了字符的ASCII码,将一个保存字符的数组的每一个元素放入一个int类型的数组中,int类型数组的下标就是字符对应的ASCII码

int js(char air[])
{
    int l=0,r=0;    //后标和前标
    int ret=0,cnt=0;    //结果,次数=回文串的大小
    int num[1000] = {0};
    int len = strlen(air);
}

先准备需要的变量

l,r是需要移动的下标,ret是最后得到的最长子串大小,cnt是操作的次数,num是用来保存字符数组的int类型数组,将数组初始化为0,代表所有字符都为出现过,在后面的操作中如果在int数组里放入字符则int类型数组值为1。len计算字符数组的大小。

#以absb为例子(num等号左边为下标,右边为值)

开始时以a为回文子串的头

下标 0 1 2 3
字符 a b a c
前标 r=0
后标 l=0
num 97 = 0 98 = 0 97 = 0 99 = 0

ret = 0;ctn = 0

  • 进行第一轮循环时
下标 0 1 2 3
字符 a b a c
前标 r=1
后标 l=0
num 97 = 1 98 = 0 97 = 0 99 = 0

ret = 1,cnt = 1

  • 进行第二轮循环时
下标 0 1 2 3
字符 a b a c
前标 r=2
后标 l=0
num 97 = 1 98 = 1 97 = 0 99 = 0

ret = 2,cnt = 2

  • 进行第三轮循环时
下标 0 1 2 3
字符 a b a c
前标 r=3
后标 l=0
num 97 = 1 98 = 1 97 = 1 99 = 0

此时发现下标为97时都为1,那么判断出aba是一个回文串,接下来让num[97] = 0,表示已经找到一组,然后重新开始查找。

移动后标,使用后标加1,cnt次数减一(表示除去a是回文串的情况)

下标 0 1 2 3
字符 a b a c
前标 r=3
后标 l=1
num 97 = 0 98 = 1 97 = 0 99 = 0

ret = 2,cnt = 1

此时b为回文子串的头,num[97] = 0,符合使r++的情况,但是已经到达循环结束条件,此时循环结束。

简单来说就是暴力枚举每一个字符,以每个字符为头,然后找出以它为头的回文字符串。然后巧妙利用结果和次数的关系找到最大的

完整代码如下:

#include 
#include 
int js(char air[]);
int main()
{
    int n;
    char air[1000000];
    scanf("%s",air);
    printf("%d",js(air));
    return 0;
}
int js(char air[])
{
    int l=0,r=0;    //左标和右标
    int ret=0,cnt=0;    //结果,次数
    int num[1000] = {0};
    int len = strlen(air);
    while(r<len)	//循环进行的条件
    {
        if(num[air[r]] == 0)	//如果字符为出现过则进入循环
        {
            num[air[r]] = 1;	//出现过的字符被标记为1
            r++;			//移动前标的值
            cnt++;			//进行的次数加1,次数就是回文串的大小

            /* 保存最大结果,使cnt不断变化得到新的值 */
            if(ret>cnt)	//使ret始终比cnt大
            {
                ret = ret;
            }
            else{
                ret = cnt;
            }        
        }
        else{
            num[air[l]] = 0;	//如果字符已经出现让字符重新归零,然后重新寻找
            l++;		//移动后标的值
            cnt--;		//让进行的次数减一
        }
    }
}

你可能感兴趣的:(C语言,c语言,算法,c++)