zoukankan      html  css  js  c++  java
  • 妮可妮可妮 [Hash]

    妮可妮可妮

    题目描述

    小P特别喜欢动画Love Live中的角色妮可,每当他听到妮可说“niconiconi”时,他总会感到特别兴奋,还会露出绅士般的微笑。
    作为一名理论计算机科学家,小P开始研究“niconiconi”这种串的特点。他发现,“niconiconi”可以拆成“ni”、“co”、“ni”、“co”、“ni”这五部分。
    对这个模型进行了抽象后,小P发现,任何形如ABABA的串都有类似的特点,其中A、B为非空串,我们称这样的串满足性质P。比如“aaaaa”就满足性质P,而“ababab”却不满足性质P。
    有了这个革命性的发现,结合他最近新学的数据结构“后缀树”,小P决定造一道题。这道题是这样的,小P给你一个仅由小写英文字母组成的串S,你拿到这个串之后,小P会问你q个问题,每个问题形如“S的后缀p是不是满足性质P的串呀”。
    注:设S的长度为n,那么S[1..n]的后缀p就是子串S[p..n]。

    输入

    第一行一个仅由小写英文字母组成的串S。
    第二行一个整数q。
    接下来q行,每行一个数p_i,表示第i次的问题是:“S的后缀p_i是不是满足性质P的串呀”。

    输出

    输出文件一共q行,第i行为对第i个问题的回答。
    如果满足性质P,回答:“niconiconi”。(不包含引号)
    如果不满足性质P,回答:“no”。(不包含引号)

    样例输入

    niconiconi
    1
    1

    样例输出

    niconiconi

    提示

    样例输入2
    orzorzorz
    3
    1
    7
    2
    样例输出2
    no
    no
    niconiconi

    测试点1..3:(|S|≤100)
    测试点1..6:(|S|≤1000)
    测试点1..10:(1≤|S|≤5*10^5,1≤q≤10^5)

    题解

    我么发现一个字符串若满足性质P,则必然可以分成[A][BA][BA]这三部分

    而后面BA可以看成一个部分,也就是求一个字串,满足ACC,其中A是C的后缀

    所以对于(60)%的数据,我们可以(O(n^2))枚举C的长度,再判断A的长度最长可以是多长,设ans[i]表示后缀i是否满足性质P,那么我们每次枚举一个C,都可以得到一段区间内ans[]都等于1

    那么怎么优化呢?我们可以发现枚举C之后,A的长度是具有单调性的,因此我们可以二分一个A的长度,这样时间复杂度就优化到了(O(n*logn))

    利用差分的思想统计哪些区间的前缀满足性质P

    这些都是预处理,最后查询的时候就是(O(1))查询

    Code

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef unsigned long long lol;
    const int N=5*1e5+10,base=31;
    
    lol Hash[N],sum[N],tq,aq[N];
    int m,x,ans[N];
    char s[N];
    
    inline lol get(int l,int r)
    {
        return Hash[r]-Hash[l-1]*sum[r-l+1];
    }
    
    int main() 
    {
        //freopen("nico.in","r",stdin);
        //freopen("nico.out","w",stdout);
        scanf("%s%d",s+1,&m);
        int n=strlen(s+1); sum[0]=1;
        for(int i=1;i<=n;i++) Hash[i]=(Hash[i-1]*base+s[i]-'a'+1),sum[i]=sum[i-1]*base;
        for(int i=1;i<=n;i++) {
            if(get(n-i+1,n)!=get(n-2*i+1,n-i)) continue;
            lol mid,l=1,r=i-1;
            while(l<r) {
                mid=l+r+1>>1;
                if(get(n-mid+1,n)!=get(n-2*i-mid+1,n-2*i)) r=mid-1;
                else l=mid;
            }
            ++aq[n-2*i-l+1],--aq[n-2*i+1];
        }
        for(int i=1;i<=n;i++) 
            tq+=aq[i],ans[i]=(tq>0);
        for(int i=1;i<=m;i++) {
            scanf("%d",&x);
            puts(ans[x]?"niconiconi":"no");
        }
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    今天下午去了佛山梁园——广东四大名园之一
    我眼中的Web2.0
    《花眼》观后感
    Implement SOAP services with the Zend Framework
    js 捕捉右键事件
    Zend Framework 第九节数据库操作学习总结
    PHP :time(),date(),mktime()日期与时间函数库{经常会忘却掉}
    zend_soap 实现 web service 用户验证
    php中DOMDocument简单用法(XML创建、添加、删除、修改)
    jquery 判断浏览器方法
  • 原文地址:https://www.cnblogs.com/real-l/p/9539056.html
Copyright © 2011-2022 走看看