码迷,mamicode.com
首页 > 其他好文 > 详细

#计算回文字符串最大长度模板题

时间:2020-02-07 13:16:22      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:编号   long   一个个   case   char s   string   子串   stream   name   

计算回文字符串最大长度模板题

如果一个字符串正着读和倒着读是一样的,则称它是回文的。

给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。

输入格式
输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出。

输入以一个以字符串“END”(不包括引号)开头的行表示输入终止。

输出格式
对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。

每个输出占一行。

输入样例:
abcbabcbabcba
abacacbaaaab
END
输出样例:
Case 1: 13
Case 2: 6

    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<cstring>
    using namespace std;
    const int N = 10000010;
    const int bace = 131;
    unsigned long long hl[N], hr[N], p[N];
    char s[N];
    unsigned long long get(unsigned long long h[], int l, int r)
    {
        return h[r] - h[l - 1] * p[r - l + 1];
    }
    int main()
    {
        p[0] = 1;
        int T = 1;
        while (cin>>s+1, strcmp(s + 1, "END"))
        {
            int n = strlen(s + 1);
            for (int i = n * 2; i > 0; i -= 2)//在每个字符中检查入一个数大于'z',这样好计算,就都变成了奇数个字符
            {
                s[i] = s[i / 2];
                s[i - 1] = 'z' + 1;
            }
            n *= 2;
            for (int i = 1, j = n; i <= n; i++, j--)//求出字符串循序和逆序的哈希值
            {
                hl[i] = hl[i - 1] * bace + (s[i] - 'a' + 1);
                hr[i] = hr[i - 1] * bace + (s[j] - 'a' + 1);
                p[i] = p[i - 1] * bace;
            }
            int ans = 0;
            for (int i = 1; i <= n; i++)//枚举1~n的字符,找到一个个数mid,使得以这个字符为中心,半径为mid的一串字符串是最长的回文字符串 形如i-mid~i~i+mid,
            {
                int l = 0, r = min(i - 1, n - i);
                while (l < r)//找到mid
                {
                    int mid = l + r + 1 >> 1;
                    if (get(hl, i - mid, i - 1) != get(hr, n - (i + mid) + 1, n - (i + 1) + 1))//计算i左边到i-mid的字符串哈希值,是不是等于i字符右边到i+mid的哈希值,为啥是n-(i+mid)+1,n-(i+1)+1呢,因为hr数组计算的就是反过来以后的哈希值,1对应的是n,x对应的就是n-x+1,
                        r = mid - 1;
                    else
                        l = mid;
                }
                if (s[i - l] <= 'z')如果i-mid的这个数是字母,就把mid+1,你可能会问不用乘以二么,其实上面就已经是乘上2
                 得了
                    ans = max(ans, l + 1);
                else//如果不是字母,就正常输出
                    ans = max(ans, l);
            }
            printf("Case %d: %d\n", T++, ans);
        }
        return 0;
    
    }

#计算回文字符串最大长度模板题

标签:编号   long   一个个   case   char s   string   子串   stream   name   

原文地址:https://www.cnblogs.com/arbor-one/p/12272348.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!