zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度

    地址 https://www.acwing.com/problem/content/141/

    如果一个字符串正着读和倒着读是一样的,则称它是回文的。
    给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。
    
    输入格式
    输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。
    输入以一个以字符串 END 开头的行表示输入终止。
    
    输出格式
    对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。
    每个输出占一行。
    
    输入样例:
    abcbabcbabcba
    abacacbaaaab
    END
    输出样例:
    Case 1: 13
    Case 2: 6
    

    解答

    1. 前置知识 字符串哈希
      对于一个长度为len的字符串str 可以使用一个数组 unsigned long long hashV[N] 来记录
      1~n的 字符串的哈希值 hashV[i]=hashV[i-1]x131 + str[i]-'a'+1;
      对于a到b的区间字符串的哈希值就是 hashV[b] - hashV[a]x131^(b-a+1)

    那么计算出字符串的正序和逆序哈希值
    以每个点展开向两旁扩展 获取哈希值 如果每个点两边的哈希值一致 那么它就是回文串记录回文串长度,返回最大值即可.

    1. 回文判断有aba和aabb两种,中间填充符号就可以直接划分为一种判断方式了
      比如转化为 a#b#a a#a#b#b

    2. 考虑到数据量较大 判断回文串的长度使用二分比遍历要快,否则会tle

    // Ac139.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <memory.h>
    
    
    using namespace std;
    
    
    /*
    如果一个字符串正着读和倒着读是一样的,则称它是回文的。
    
    给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。
    
    输入格式
    输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。
    
    输入以一个以字符串 END 开头的行表示输入终止。
    
    输出格式
    对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。
    
    每个输出占一行。
    
    输入样例:
    abcbabcbabcba
    abacacbaaaab
    END
    输出样例:
    Case 1: 13
    Case 2: 6
    */
    
    
    const int N = 2001000;
    //const int N = 1001000;
    unsigned long long lh[N];
    unsigned long long rh[N];
    unsigned long long p[N];
    const int base = 131;
    char str[N];
    char cpStr[N];
    int ans = 1;
    
    
    unsigned long long GetHashVl(unsigned long long h[N], int l, int r)
    {
    	return h[r] - h[l - 1] * p[r - l + 1];
    }
    
    unsigned long long GetHashVr(unsigned long long h[N], int l, int r)
    {
    	return h[l] - h[r + 1] * p[r - l + 1];
    }
    
    int GetRealLen(int len, char c) {
    	if (c == '#') {
    		if (len % 2 == 0) return len;
    		else return (len / 2 + 1) * 2;
    	}
    	else {
    		if (len % 2 == 0) return len + 1;
    		else return (len / 2) * 2 + 1;
    	}
    }
    
    int main()
    {
    	int idx = 1;
    	while (1) {
    		ans = 1;
    		memset(cpStr, 0, sizeof(cpStr));
    		memset(lh, 0, sizeof lh);
    		memset(rh, 0, sizeof lh);
    
     
    		scanf("%s", str + 1);
    		if (strcmp(str + 1, "END") == 0) { break; }
    		int len = strlen(str + 1);
    		memset(cpStr, 0, sizeof(cpStr));
    		for (int i = 0; i < len; i++) {
    			cpStr[i * 2 + 1] = str[i + 1];
    			cpStr[i * 2 + 2] = '#';
    		}
            
    		//计算正向逆向的哈希值的 然后遍历字节得到以遍历点为中心的最长回文长度
    		len = strlen(cpStr + 1) - 1;
    		cpStr[len + 1] = '';
    		p[0] = 1;
    		for (int i = 1; i <= len; i++) {
    			lh[i] = lh[i - 1] * base + cpStr[i] - 'a' + 1;
    			int j = len - i + 1;
    			rh[j] = rh[j + 1] * base + cpStr[j] - 'a' + 1;
    			p[i] = p[i - 1] * base;
    		}
    
    		for (int i = 1; i <= len; i++) {
    			int r = min(i - 1, len - i);
    			int l = 0;
    
    			while (l < r) {
    				int mid = (l + r+1) >> 1;
    				if (GetHashVl(lh, i - mid, i) != GetHashVr(rh, i, i + mid)) {
    					r = mid-1;
    				}
    				else {
    					l = mid ;
    				}
    			}
    
    			int realLen = GetRealLen(l, cpStr[i]);
    			ans = max(ans, realLen);
    		}
    
    		printf("Case %d: %d
    ", idx++, ans);
    	}
    
    
    	return 0;
    }
    
    

    我的视频题解空间

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    进入MFC讲坛的前言(四)
    进入MFC讲坛的前言(二)
    进入MFC讲坛的前言(一)
    进入MFC讲坛的前言(三)
    jar命令+7z:创建,替换,修改,删除Jar, war, ear包中的文件
    java架构之项目结构(entity / DTO / VO)
    面试无忧之Zookeeper总结心得
    BigDecimal.setScale 处理java小数点
    最详细的 paypal 支付接口开发--Java版
    社会化登录分享-Android SDK的二次封装和使用
  • 原文地址:https://www.cnblogs.com/itdef/p/14780528.html
Copyright © 2011-2022 走看看