• 动物园


    Smiling & Weeping

                    ---- 你是我的,半截的诗,不许别人更改一个字

     

    题目链接:P2375 [NOI2014] 动物园 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

    思路详解:这道题目是要求解:有多少个我现在希望求出一个更强大 num 数组一一对于字符串 S 的前 i 个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。

      其实,我刚开始是想求解公共最长前后缀再加上跳跃优化~o(╥﹏╥)o这是个错误的思路

     然后,又用s和s的每个后缀的LCP 结合 公共最长前后缀 再加上跳跃优化o(╥﹏╥)o 很可惜TLE

      最后,一想,为什么不能把思路化简一下呢,只求每个(s[0] == s[i])的LCP,仔细想想是不是这样,在这个区间的每个字母都会有这样一个以s[i]为开头的前缀,然后len=min(i , nxt[i])(不能重叠,并且有公共部分),将i~i+len-1部分的num[i]++,思路很清晰,代码也很好实现,(⊙︿⊙) + o(╥﹏╥)o 很可惜TLE ,最后使用 前缀和 和 差分 来小小的优化一波,AC

    Talk is cheap , show me the code

    复制代码
     1 #include
     2 using namespace std;
     3 typedef long long ll;
     4 const int mode = 1000000007;
     5 int n , Next[1000100] , slen;
     6 int nxt[1000100] , num[1000100];
     7 ll ans;
     8 char str[1000100];
     9 void getnext(char *s , int slen){
    10     int p=0 , k=1,l;
    11     nxt[0] = slen;
    12     while(p+1 < slen && s[p]==s[p+1]) p++;
    13     nxt[1] = p;
    14     for(int i = 2; i < slen; i++){
    15         p = k+nxt[k]-1;
    16         l = nxt[i-k];
    17         if(i+l <= p) nxt[i] = l;
    18         else {
    19             int j = max(0 , p-i+1);
    20             while(i+j < slen && s[i+j] == s[j]) j++;
    21             nxt[i] = j;
    22             k = i;
    23         }
    24     }
    25 }
    26 void solve(){
    27     for(int i = 1; i < slen; i++){
    28         if(str[i] == str[0]){
    29             int len = min(i , nxt[i]);
    30             // 会被卡,TLE,改用前缀和,可以通过
    31             // for(int j = i; j <= i+len-1; j++)
    32             //     num[i]++;
    33             num[i]++; num[i+len]--;
    34         }
    35     }
    36     for(int i = 1; i < slen; i++)
    37         num[i] += num[i-1];
    38 }
    39 int main()
    40 {
    41     scanf("%d",&n);
    42     while(n--){
    43         ans = 1;
    44         scanf("%s",str);
    45         slen = strlen(str);
    46         getnext(str , slen);
    47         solve();
    48         for(int i = 1; i < slen; i++)
    49             ans = ans*(num[i]+1)%mode , num[i] = 0;
    50         printf("%lld",ans);
    51         if(n) printf("\n");
    52     }
    53     return 0;
    54 }
    复制代码

    不要因为也许会改变,就不肯说那句美丽的誓言;

    不要因为也许会分离,就不敢求一次倾心的相遇;

    文章到此结束,我们下次再见 跳舞(((((ી(・◡・)ʃ)))))

  • 相关阅读:
    Springboot整合JavaMail(发送邮件)
    第4章:网络层
    Visual Studio部署C++矩阵库Armadillo的方法
    记账心得分享
    vue3+ts封装弹窗,分页封装
    大数据采集工具Flume
    Shell 编程之免交互
    【2023秋招面经】4399 前端 二面-hr面(20min)
    微信DAT文件解密(dat转图像)
    【Docker故障处理篇】运行容器报错“docker: failed to register layer...file exists.”解决方法
  • 原文地址:https://www.cnblogs.com/smiling-weeping-zhr/p/17688651.html