B. Password(字符串哈希+二分)

62 篇文章 2 订阅
11 篇文章 0 订阅

https://codeforces.com/problemset/problem/126/B

题意翻译

Asterix,Obelix和他们的临时伙伴Suffix、Prefix已经最终找到了和谐寺。然而和谐寺大门紧闭,就连Obelix的运气也没好到能打开它。

不久他们发现了一个字符串S(|S|<=1000000),刻在和谐寺大门下面的岩石上。Asterix猜想那一定是打开寺庙大门的密码,于是就大声将字符串朗读了出来,然而并没有什么事发生。于是Asterix又猜想密码一定是字符串S的子串T。

Prefix认为T是S的前缀,Suffix认为T是S的后缀,Obelix却认为T应该是S中的某一部分,也就是说,T既不是S的前缀,也不是S的后缀。

Asterix选择子串T来满足所有伙伴们的想法。同时,在所有可以被接受的子串变形中,Asterix选择了最长的一个(因为Asterix喜欢长的字符串)当Asterix大声读出子串T时,寺庙的大门开了。 (也就是说,你需要找到既是S的前缀又是S的后缀同时又在S中间出现过的最长子串)

现在给你字符串S,你需要找到满足上述要求的子串T。

输入格式:

一个长度在[1,1000000]间的只包含小写字母的字符串S。

输出格式:

输出子串T,如果T不存在,输出 "Just a legend",不包含引号。


思路:

对于一个前缀 ,如果存在一个不在最左边也不在最右边的子串 ,那么一个比当前短的前缀也一定能找到对应的子串。

所以我们先预处理找出所有合法的前缀 (合法:有对应的后缀),然后二分判当前长度在中间段是否存在满足的子串,满足的话继续延长(l=mid)

启发:一些字符串题可以利用长串满足短串一定满足的性质去思考

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e6+100;
typedef long long LL;
const LL mod=998244353;
const LL p=131;
LL f[maxn],h[maxn];
LL a[maxn],tot=0;
LL n;
string s=" ";
LL cal(LL l,LL r){
    return (f[r]%mod-f[l-1]*h[r-l+1]%mod+mod)%mod;
}
bool check(LL len,LL val){
    for(LL i=2;i+len-1<n;i++){
        if(cal(i,i+len-1)==val) return true;
    }
    return false;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  h[0]=1;
  for(LL i=1;i<maxn;i++) h[i]=h[i-1]*p%mod;
  string c;cin>>c;
  s+=c;
  n=s.size()-1;
  for(LL i=1;i<=n;i++){
     f[i]=(f[i-1]*p%mod+s[i])%mod;
  }
  for(LL i=1;i<=n;i++){
    if(cal(1,i)==cal(n-i+1,n)){
        a[++tot]=i;
    }
  }
  LL l=0;LL r=tot;
  while(l<r){
    LL mid=(l+r+1)>>1;
    if(check(a[mid],cal(1,a[mid]))) l=mid;
    else r=mid-1;
  }
  if(l==0){
    cout<<"Just a legend"<<endl;
  }
  else{
    for(LL i=1;i<=a[l];i++){
        cout<<s[i];
    }
    cout<<endl;
  }
return 0;
}

 

字符串哈希滑动窗口是一种用于处理字符串的算法。它主要用于在给定的字符串中找到满足特定条件的子串。 在字符串哈希滑动窗口算法中,我们首先计算原始字符串哈希值。然后,我们使用一个滑动窗口来遍历字符串,每次滑动一个固定长度的窗口。我们可以通过比较每个窗口内的子串的哈希值来判断是否满足条件。 具体而言,我们可以使用BKDRHash等哈希函数来计算字符串哈希值。然后,我们枚举每个可能的起点,并使用滑动窗口来计算窗口内的子串的哈希值。通过比较窗口内的子串的哈希值,我们可以判断是否满足条件。 对于滑动窗口的移动,如果窗口内的子串满足条件,我们可以继续将窗口往右移动一个固定的长度。如果窗口内的子串不满足条件,我们将窗口的右边界移到最右端,并依次比较新窗口内的子串的哈希值。 综上所述,字符串哈希滑动窗口算法是通过计算字符串哈希值,并使用滑动窗口来遍历字符串,以找到满足特定条件的子串。这个算法可以高效地处理字符串,并且能够应用于各种字符串相关的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [String (字符串哈希+滑动窗口)](https://blog.csdn.net/weixin_43872264/article/details/107571742)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【字符串hash+滑动窗口】String HDU - 4821](https://blog.csdn.net/qq_45599865/article/details/111143633)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值