zoukankan      html  css  js  c++  java
  • 妮可妮可妮

    【问题描述】
    小 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]。


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

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


    【数据范围】
    测试点 1..3:|S|≤100
    测试点 1..6:|S|≤1000
    测 试 点
    1..10 : 1 ≤ |S| ≤ 5*10 5 , 1 ≤ q ≤ 10 5

    形如ABABA的串,可以化为(端点)A(断点2)[BA(2)](断点1)[BA(1)]

    我们令f[i]为1~i与1~n 的最长公共后缀

    枚举断点1为i

    [BA(1)]=str[i~n]

    [BA(2)]=str[j~i-1]   (n-i+1=i-j)

    则端点的范围为j-min(g[j-1],n-i)

    则j-min(g[j-1],n-i)~~j-1的后缀显然都符合ABABA

    那么有几个问题:

    1.怎麽求出f[i],用二分,二分长度并匹配,匹配失败则缩小长度

    2.怎麽快速判断字符串相同,用字符串hash

    3.j-min(g[j-1],n-i)~~j-1用差分数组全部+1,就可以O(1)查询

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long lol;
     7 lol p=31,Mod=1000000007,ha[500005],pw[500005];
     8 char s[500001];
     9 int f[500005],ans[500005],len;
    10 lol hash(int l,int r)
    11 {
    12   return (ha[r]-(ha[l-1]*pw[r-l+1])%Mod+Mod)%Mod;
    13 }
    14 int main()
    15 {int i,j,x;
    16   scanf("%s",s+1);
    17   len=strlen(s+1);
    18   pw[1]=p;
    19   pw[0]=1;
    20   ha[1]=s[1]-'a';
    21   for (i=2;i<=len;i++)
    22     ha[i]=(ha[i-1]*p+(s[i]-'a'))%Mod,pw[i]=(pw[i-1]*p)%Mod;
    23   for (i=1;i<=len;i++)
    24     {int l,r,as;
    25       l=0;r=i;as=0;
    26       while (l<=r)
    27     {
    28       int mid=(l+r)/2;
    29       if (hash(i-mid+1,i)==hash(len-mid+1,len)) as=mid,l=mid+1;
    30       else r=mid-1;
    31     }
    32       f[i]=as;
    33     }
    34   for (i=len-1;i>=1;i--)
    35     {
    36       int l=len-i+1,j=i-l;
    37       if (j>1)
    38       if (f[i-1]>=l)
    39     {
    40       int ll=j-min(f[j-1],l-1);
    41       ans[ll]++;ans[j]--; 
    42     }
    43     }
    44   for (i=1;i<=len;i++)
    45     {
    46       ans[i]+=ans[i-1];
    47     }
    48   int q;
    49   cin>>q;
    50   while (q--)
    51     {
    52       scanf("%d",&x);
    53       if (ans[x]) printf("niconiconi
    ");
    54       else printf("no
    ");
    55     }
    56 }
  • 相关阅读:
    DTD和Schema的区别
    在使用Maven中出现的小错误
    struts2 中 paramsPrepareParamsStack 拦截器
    Hibernate的save()和persist()的区别
    Spring学习笔记
    Hello Spring
    Hibernate3 和Hibernate4 在配置文件上的区别
    今日学习-商品数据库查询
    Java中避免表单重复提交
    Java学习笔记
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7561751.html
Copyright © 2011-2022 走看看