关闭

BZOJ3620: 似乎在梦中见过的样子 KMP

172人阅读 评论(0) 收藏 举报
分类:

题意:给出一个小写字母字符串,求形如ABA(A的长度>=k)的子串个数。位置不同其他性质相同的子串算不同子串,位置相同但拆分不同的子串算同一子串。
n<=15000 , k<=100
暴力枚举左右端点就能过。
枚举每个左端点当做首字符进行KMP,对于一个右端点,沿着fail指针跳回去,经过的节点能满足”首字符到这个字符构成的前缀也是当前的后缀“。所以找到一个尽可能长的匹配前缀使得len*2+1<=当前区间长度(因为B这个成分至少要占一个字符),判断len是否大于K即可。

#include<cstdio>
using namespace std;
char t[20000],k;
long long ans=0;
inline long long count(const char *s)
{
    static int nexus[15000]={-1};
    long long res=0;
    for(int i=1;s[i];++i)
    {
        int &fail=nexus[i]=nexus[i-1];
        while(~fail&&s[fail+1]!=s[i]) fail=nexus[fail];
        if(s[fail+1]==s[i]) ++fail;
        int cp=fail;
        while(~cp&&(cp+1<<1)>=(i+1)) cp=nexus[cp];
        if(cp+1>=k) ++res;
    }
    return res;
}
int main()
{
    scanf("%s%d",t,&k);
    for(int i=0;t[i];++i)
    ans+=count(t+i);
    printf("%lld\n",ans);
    return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:20190次
    • 积分:1096
    • 等级:
    • 排名:千里之外
    • 原创:90篇
    • 转载:0篇
    • 译文:0篇
    • 评论:18条
    博客专栏