【数据结构与算法】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为回文子串的头

下标0123
字符abac
前标r=0
后标l=0
num97 = 098 = 097 = 099 = 0

ret = 0;ctn = 0

  • 进行第一轮循环时
下标0123
字符abac
前标r=1
后标l=0
num97 = 198 = 097 = 099 = 0

ret = 1,cnt = 1

  • 进行第二轮循环时
下标0123
字符abac
前标r=2
后标l=0
num97 = 198 = 197 = 099 = 0

ret = 2,cnt = 2

  • 进行第三轮循环时
下标0123
字符abac
前标r=3
后标l=0
num97 = 198 = 197 = 199 = 0

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

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

下标0123
字符abac
前标r=3
后标l=1
num97 = 098 = 197 = 099 = 0

ret = 2,cnt = 1

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

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

完整代码如下:

#include <stdio.h>
#include <string.h>
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--;		//让进行的次数减一
        }
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼小小虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值