• Codeforces1326D Prefix-Suffix Palindrome


    一道字符串题,比赛的时候太困了,一开始先想着去搜搜有没有什么结论 (+) 板子往上面套了……

    其实 (12:00) 的时候发现这个是 (hash) 了,然而太困了没写动,还 (WA)

    Description

    link

    给定一个字符串。要求选取他的一个前缀(可以为空)和与该前缀不相交的一个后缀(可以为空)拼接成回文串,且该回文串长度最大。求该最大长度。

    多组数据。保证 (sum |s|leq 10^6)

    Solution

    首先是个 (O(n)) 题吧,之后发现回文串,考虑 (hash)

    我们发现答案可能由几部分组成:

    1.直接看两头的回文

    2.删掉两头的回文之后的字符串的最长的回文前缀 (or) 后缀

    (脑子清醒的时候这玩意好简单)

    第一部分略

    第二部分直接上 (hash)

    附:判断一个字符串是否回文的 (O(1)) 做法(那个预处理忽略谢谢)

    res=(hash[r]-hash[l-1]*pow[r-l+1]%mod+mod)%mod;
    

    记前缀后缀两个 (hash) 值,然后每次判断一下就 (OK)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=1e6+10,base=2333333,mod=1e9+9;
    	int pre[N],suf[N],p[N];
    	char s[N]; 
    	inline bool check(int l,int r)
    	{
    		int res1=(pre[r]-pre[l-1]*p[r-l+1]%mod+mod)%mod;
    		int res2=(suf[l]-suf[r+1]*p[r-l+1]%mod+mod)%mod;
    		return res1==res2;
    	}
    	inline void work()
    	{
    		scanf("%s",s+1); int len=strlen(s+1),k=0;
    		while(k<len/2&&s[k+1]==s[len-k]) ++k; 
    		pre[k]=suf[len-k+1]=0;
    		for(int i=k+1;i<=len-k;++i) pre[i]=pre[i-1]*base+s[i],pre[i]%=mod;
    		for(int i=len-k;i>k;--i) suf[i]=suf[i+1]*base+s[i],suf[i]%=mod;
    		for(int now=len-(k<<1);now>=0;--now)
    		{
    			if(check(k+1,k+now)) 
    			{
    				for(int i=1;i<=k+now;++i) printf("%c",s[i]);
    				for(int i=len-k+1;i<=len;++i) printf("%c",s[i]);
    				return puts(""),void();
    			}
    			if(check(len-k-now+1,len-k))
    			{
    				for(int i=1;i<=k;++i) printf("%c",s[i]);
    				for(int i=len-k-now+1;i<=len;++i) printf("%c",s[i]);
    				return puts(""),void(); 
    			 } 
    		 } 
    		return ;
    	}
    	signed main()
    	{
    		p[0]=1; for(int i=1;i<N;++i) p[i]=p[i-1]*base%mod; 
    		int T=read(); while(T--) work();
    		return 0;
    	}
    }
    signed main(){return yspm::main();} 
    
  • 相关阅读:
    访问者模式(Visitor)
    策略模式
    职责链模式(Chain of Responsibility)
    模版方法模式
    逃离大厦第80关与马踏棋盘
    结合JDK源码看设计模式——迭代器模式
    Java并发——线程介绍
    结合JDK源码看设计模式——模板方法模式
    结合JDK源码看设计模式——桥接模式
    结合JDK源码看设计模式——组合模式
  • 原文地址:https://www.cnblogs.com/yspm/p/12548054.html
Copyright © 2020-2023  润新知