• Just A String(kmp)


    链接:https://ac.nowcoder.com/acm/problem/13821
    来源:牛客网

    题目描述

    何老师手中有一个字符串S,他发现这个字符串有一个神奇的性质,取出一个长为i的前缀(就是由S的前i个字符顺序构成的字符串)prei和一个长为j的后缀(就是由S的后j个字符顺序构成的字符串)sufj之后,总是存在三个字符串A,B,C(可能为空)使得prei=A+B,sufj=B+C, 虽然这听起来像是一句废话。 
    显然三元组A,B,C不总是唯一的,何老师从所有可能的三元组中找到B最长的,很容易知道这样的三元组是唯一的,并且认为prei和sufj的契合度就是f(i,j)=|A|*|B|*|B|*|C|,现在你需要帮何老师算出所有f(i,j)(0 ≤ i,j ≤ n)的异或和。 
    这里|X|表示字符串X的长度,X+Y表示将两个字符串X和Y顺序拼接起来后得到的新字符串。

    输入描述:

    第一行是一个正整数T(≤ 500),表示测试数据的组数, 每组测试数据,包含一个仅由小写字母构成的非空字符串S(|S| ≤ 2000), 保证满足|S|>200的数据不超过5组。

    输出描述:

    对于每组测试数据,输出所有f(i,j)(0 ≤ i,j ≤ n)的异或和。

    具体思路:

    首先,我们枚举每个后缀,判断当前总的字符串从第0个位置开始到这个字符串的i位置与当前枚举的后缀的重叠长度。

    这个过程和kmp的nex数组是类似的。

    nex[i]代表的是从0开始到第i个位置,前缀和后缀完全匹配的最大长度。

    com[i]就代表从0到i这个字符串后缀与匹配串前缀的重叠长度。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 # define inf 0x3f3f3f3f
     5 const int  maxn = 2e5+100;
     6 char str[maxn];
     7 int nex[maxn];
     8 int  com[maxn];
     9 void getnex(char *s)
    10 {
    11     nex[0]=nex[1]=0;
    12     int len=strlen(s);
    13     for(int i=1; i<len; i++)
    14     {
    15         ll j=nex[i];
    16         while(j&&s[i]!=s[j])
    17             j=nex[j];
    18         nex[i+1]= (s[i]==s[j]?j+1:0);
    19     }
    20 }
    21 void kmp(char *str1,char *str2)
    22 {
    23     getnex(str2);
    24     int len1=strlen(str1);
    25     int len2=strlen(str2);
    26     ll j=0;
    27     for(int i=0; i<len1; i++)
    28     {
    29         while(j&&str1[i]!=str2[j])
    30             j=nex[j];
    31         if(str1[i]==str2[j])
    32             j++;
    33         if(j==0)
    34             com[i]=0;
    35         else
    36             com[i]=j;
    37         if(j==len2)
    38             j=nex[j];
    39     }
    40 }
    41 int main()
    42 {
    43     int T;
    44     scanf("%d",&T);
    45     while(T--)
    46     {
    47         ll ans=0;
    48         scanf("%s",str);
    49         int len=strlen(str);
    50         for(int i=1; i<=len; i++)
    51         {
    52             for(int j=0; j<=len; j++)
    53                 com[j]=0;
    54             kmp(str,str+(len-i));
    55             for(int j=0; j<len; j++)
    56             {
    57                 ll  A=j+1-com[j];
    58                 ll  B= com[j];
    59                 ll C= i-com[j];
    60                 ll tmp=A*B*B*C;
    61                 ans^=tmp;
    62             }
    63             //  cout<<i<<" "
    64         }
    65         printf("%lld
    ",ans);
    66     }
    67     return 0;
    68 }

    我的kmp代码不知道哪里错了,样例过了,但是提交却一组也不对。希望路过的神仙看一下哪里的问题 !!!∑(゚Д゚ノ)ノ

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 # define inf 0x3f3f3f3f
     5 const int  maxn = 2e5+100;
     6 char str[maxn];
     7 int nex[maxn];
     8 int  com[maxn];
     9 void getnex(char *s)
    10 {
    11     int len=strlen(s);
    12     nex[0]=-1;
    13     int i=0,j=-1;
    14     while(i<len)
    15     {
    16         if(j==-1||s[i]==s[j])
    17         {
    18             i++;
    19             j++;
    20             nex[i]=j;
    21         }
    22         else
    23             j=nex[j];
    24     }
    25 }
    26 void kmp(char *str1,char *str2)
    27 {
    28     getnex(str2);
    29     int len1=strlen(str1);
    30     int len2=strlen(str2);
    31     int i=0,j=0;
    32     while(i<len1&&j<len2)
    33     {
    34         if(j==-1||str1[i]==str2[j])
    35         {
    36             i++;
    37             j++;
    38         }
    39         else
    40             j=nex[j];
    41         com[i-1]= ( j==-1? 0 : j );
    42         if(j==len2)
    43             j=nex[j];
    44     }
    45 }
    46 int main()
    47 {
    48     int T;
    49     scanf("%d",&T);
    50     while(T--)
    51     {
    52        ll ans=0;
    53         scanf("%s",str);
    54         int len=strlen(str);
    55         for(int i=1; i<=len; i++)
    56         {
    57             for(int j=0; j<=len; j++)
    58                 com[j]=0;
    59             kmp(str,str+(len-i));
    60             for(int j=0; j<len; j++)
    61             {
    62                 ll  A=j+1-com[j];
    63               ll  B= com[j];
    64                ll C= i-com[j];
    65                 ll tmp=A*B*B*C;
    66                 ans^=tmp;
    67             }
    68           //  cout<<i<<" "
    69         }
    70         printf("%lld
    ",ans);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    模态框获取内容jQuery
    jQuery支持链式编程,一句话实现左侧table页+常用筛选器总结
    jquery实现全选、取消反选、加JavaScript三元运算(三种法法实现反选)
    用dom1来实现,根据光标移动自动给表单加上背景色,光标移开自动去除背景色
    JavaScript两种创建标签的的方法,实现点击按钮让text自增
    vue前端路由搜索功能实现
    pycharm配置vue
    QT全局事件和绑定
    mysql事务、锁
    web前端上传文件按钮自定义样式
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10906405.html
Copyright © 2020-2023  润新知