zoukankan      html  css  js  c++  java
  • 【ybtoj】【Hash】回文子串

    题意

    题目描述

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

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

    输入格式

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

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

    输出格式

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

    样例

    样例输入

    abcbabcbabcba
    abacacbaaaab
    END
    

    样例输出

    Case 1: 13 
    Case 2: 6

    题解

    回文串还是经常遇见的一种题,所以第一时间想到:答案满足单调性所以二分长度,check函数里O(N)判断是否有长度为 mid 的回文串

    有几个需要注意的点(我一开始没想到的):

    • 回文串要分奇回文和偶回文讨论
    • 存下反串和原串是对称的,写check的时候要注意一下

    代码

    回文子串
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF = 0x3f3f3f3f,N = 1e6+10,mod = 1e9+7,base = 233;
    ll mi[N<<1],sum[N<<1];
    int len,cnt;
    char s[N<<1];
    void init()
    {
    	mi[0]=1;
    	for(int i=1;i<=len<<1;i++)
    	{
    		sum[i]=sum[i-1]*base+s[i]-'a'+1,sum[i]%=mod;
    		mi[i]=mi[i-1]*base,mi[i]%=mod;
    	}
    }
    inline ll Hash(int l,int r)
    {
    	return (sum[r]-sum[l-1]*mi[r-l+1]%mod+mod)%mod;
    }
    inline bool check1(int mid)
    {
    	for(int i=mid+1;i+mid<=len;i++)
    		if(Hash(i-mid,i+mid)==Hash(len*2-(i+mid)+1,len*2-(i-mid)+1))
    		{
    			//printf("[%d,%d]==[%d,%d]
    ",i-mid,i+mid,len*2-(i+mid)+1,len*2-(i-mid)+1);
    			return true;
    		}
    	return false;
    }
    inline bool check2(int mid)
    {
    	for(int i=mid;i+mid<=len;i++)
    		if(Hash(i-mid+1,i+mid)==Hash(len*2-(i+mid)+1,len*2-(i-mid+1)+1))
    		{
    			//printf("[%d,%d]==[%d,%d]
    ",i-mid,i+mid,len*2-(i+mid)+1,len*2-(i-mid)+1);
    			return true;
    		}
    	return false;
    }
    int main()
    {
    	while(1)
    	{
    		cnt++;
    		scanf("%s",s+1);
    		if(s[1]=='E'&&s[2]=='N'&&s[3]=='D') break;
    		len=strlen(s+1);
    		for(int i=1;i<=len;i++) s[i+len]=s[len-i+1];//在S末尾把反串存下来 
    		init();
    		int l=0,r=len,ans1=0,ans2=0;
    		while(l<r)//奇回文 
    		{
    			int mid=(l+r+1)>>1;
    			if(check1(mid)) l=mid;
    			else r=mid-1;
    		}
    		ans1=(l<<1)+1;
    		l=0,r=len;
    		while(l<r)//偶回文 
    		{
    			int mid=(l+r+1)>>1;
    			if(check2(mid)) l=mid;
    			else r=mid-1;
    		}
    		ans2=(l<<1);
    		printf("Case %d: %d
    ",cnt,max(ans1,ans2));
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    1.python全栈之路:python基础
    21、指定元素置后——数组
    20、泰勒展开式
    19、显示表达式的运算形式
    1、模拟蚂蚁借呗—利息计算
    05、C语言——循环结构
    04、C语言——选择结构
    03、C语言——顺序结构
    02、C语言——C语言组成与数据
    07、C语言——函数
  • 原文地址:https://www.cnblogs.com/conprour/p/15232182.html
Copyright © 2011-2022 走看看