HDU3336

HDU3336-KMP Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3838    Accepted Submission(s): 1793 Problem Description It is well kn 阅读详情

看到题目的第一反应是:这不是AC自动机模板么…每次截取子串然后添加到trie树中,然后跑一遍匹配即可…然后妥妥tle了…正解应该基于这样的考虑:在kmp算法中,我们的next数组其实是对应了模式串在当前位置能否在之前的位置中找到与当前后缀相同的前缀字符串,那么如果当前位置对应的next不是0的话,就说明前缀字符串在当前位置找到了一个匹配,也就是题目中的要求;因此,其实统计一遍next即可;
但是要注意两点:1.next对应值为0或-1时不匹配.因为位置为0其实是说明当前位置不存在相同的后缀。
2.比较next与平时不一样,平时只要比较到size()-1,因为最后一个如果相同,那么就可以滚了。但是现在是要统计出现的次数,所以要比较到最后一位的后一位。
暴力:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int mod=10007;
struct node{
    node*next1[26];
    node*fail;
    int sum;
    node(){
        memset(next1,0,sizeof(next1));fail=NULL;sum=0;
    }
}*root=new node();
int cnt=0;
void insert(string str)
{
    node*p=root;
    for(int i=0;i<str.size();i++){
        int x=str[i]-'a';
        if(!p->next1[x]){
            node*t=new node();p->next1[x]=t;
        }
        p=p->next1[x];
    }
    p->sum++;
}
void build_fail_pointer(void)
{
    node*p,*temp;
    queue<node*>que;que.push(root);
    while(!que.empty()){
        temp=que.front();que.pop();
        for(int i=0;i<26;i++){
            if(temp->next1[i]){
                if(temp==root){
                    temp->next1[i]->fail=root;
                }
                else{
                    p=temp->fail;
                    while(p){
                        if(p->next1[i]){
                            temp->next1[i]->fail=p->next1[i];break;
                        }
                        p=p->fail;
                    }
                    if(!p)temp->next1[i]->fail=root;
                }
                que.push(temp->next1[i]);
            }
        }
    }
}
void ac_automation(string str)
{
    node*p=root;
    for(int i=0;i<str.size();i++){
        int x=str[i]-'a';
        while(!p->next1[x]&&p!=root)p=p->fail;
        p=p->next1[x];
        if(!p)p=root;
        node*temp=p;
        while(temp!=root){
            if(temp->sum){
                cnt++;if(cnt==mod)cnt=0;
            }
            //else break;//**如果不只是需要知道模式串是否出现过而**
            //**是要找出所有出现的位置的话,这一行是不能要的!!!!!!**
            //并且,根据观察,没有这一行似乎并不会导致答案错误,只是时间会增加;
            //但是,有这一行却可能导致答案错误
            temp=temp->fail;
        }
    }
}
void dl(node*p)
{
    for(int i=0;i<26;i++)
        if(p->next1[i])dl(p->next1[i]);
    if(p!=root)delete p;
}
int main()
{
    freopen("test.in"  ,"r",stdin);
    freopen("test2.out","w",stdout);
    int n,i,j;string str;int t;
    cin>>t;
    while(t--){
        cin>>n;getchar();getline(cin,str);string temp;
        dl(root);for(i=0;i<26;i++)root->next1[i]=NULL;root->fail=NULL;root->sum=0;
        for(i=1;i<=n;i++){
            temp=str.substr(0,i);insert(temp);
        }
        build_fail_pointer();
        cnt=0;ac_automation(str);
        cout<<cnt<<endl;
    }

    return 0;
}

正解:

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int next1[200005];
const int mod=10007;
void getnext(string str)
{
    next1[0]=-1;
    int j=0,k=-1;
    while(j<str.size()){
        if(k==-1||str[j]==str[k]){
            j++;k++;next1[j]=k;
        }
        else{
            k=next1[k];
        }
    }
}
int main()
{
    freopen("test.in"  ,"r",stdin);
    freopen("test1.out","w",stdout);
    int t,n,i,j;string str;
    cin>>t;
    while(t--){
        cin>>n;getchar();getline(cin,str);
        getnext(str);i=0,j=0;int ans=str.size()%mod;
        while(i<=str.size()){
            j=i;i++;//cout<<next1[j]<<endl;
            while(next1[j]>0){
                ans+=1;j=next1[j];
            }
            ans%=mod;
        }
        cout<<ans<<endl;
    }

    return 0;
}

数据生成器:

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
    freopen("test.in","w",stdout);
    srand(time(0));
    int t=rand()%100+1;
    while(t--){
        int len=rand()%100+1;
        cout<<len<<endl;
        for(int i=1;i<=len;i++){
            cout<<char(rand()%26+'a');
        }
        cout<<endl;
    }

    return 0;
}

比较:

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
int main()
{
    int tmp=0;
    for(int i=1;i<=100;i++){
        system("./data");
        system("./test1");
        system("./test2");

        //if(i/100>tmp) {printf("-- %d --\n",i);tmp=i/100;}
        if(system("diff test1.out test2.out"))
        {
            printf("wrong in --> %d \n",i);
            break;
        }
        else cout<<"Test #"<<i<<" :No problem!"<<endl;
    }
    return 0;
}  
hdu3336(kmp)Count the string Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10970    Accepted Submission(s): 5109 Problem Description It is we 阅读详情

相关推荐

AI落地困局与破局者FDE:从技术神话到价值实干的战略转型

AI落地困局与破局者FDE:从技术神话到价值实干的战略转型 当前AI企业级应用面临三大核心挑战:业务场景深度非标化、技术落地"最后一公里"困局、以及市场竞争焦点转向实用价值。前线部署工程师(FDE)作为破局关键,通过技术-业务-产品三维交汇的复合能力,将AI从实验室推向生产环境。FDE不仅是技术架构师,更是业务价值挖掘机和产品进化传感器,通过"碎石路-高速公路"双循环模式,将定制化需求沉淀为可复用的平台能力。这种模式颠覆了传统SaaS的销售逻辑,形成基于价值的J型增长

随笔记录-分享&记忆 3992

HDU 3336 Count the string(KMP+DP)

求字符串中的每一个前缀在字符串中的出现个数 样例解释 :a 出现两次,ab 两次 ,aba 一次,abab 一次 next[i] 不为 0,说明出现过前缀,改前缀的贡献会在出现一次,所以 dp[i]=dp[next[i]]+1 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define rush() int T;c...

C_Dreamy的博客 502

步进电机

步进电机

happygrilclh的博客 2140

HDU(3336)

给出一段字符串s时,我们可以写出该字符串的所有非空前缀。 例如:s: "abab" 前缀是,a, ab, aba, abab 其中 a,ab出现俩次 所以所有非空前缀的总和为=1*2+1*2+1+1=6;

m0_52262443的博客 444

5分钟搞定Google Custom Search API申请:从注册到获取CX Key全流程

本文详细介绍了如何快速申请和配置Google Custom Search API,从Google Cloud项目创建、启用计费、获取API Key,到在Programmable Search Engine控制台创建自定义搜索引擎并获取关键的CX Key,提供了全流程实战指南。文章还包含安全配置建议、API调用测试方法及前端与后端的集成代码示例,帮助开发者高效实现网站或应用的智能搜索功能。

weixin_29227585的博客 1664

从零到一:Livox Mid-360 激光雷达的硬件集成与避坑实战

本文详细介绍了Livox Mid-360激光雷达的硬件集成全流程,包括硬件准备、网络配置、驱动编译和常见问题解决方案。通过实战经验,帮助开发者高效完成从设备拆箱到数据输出的完整链路,避免在IP设置、驱动编译和固件兼容性等环节踩坑。

salt的博客 1028

HDU3336------KMP+DP

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3336 题目意思: 给你一个字符串,要求求出所求的前缀在字符串一共出现了多少次 解题思路: KMP+DP 我们令dp[i]表示以s[i]结尾的字符串中出现了几个以s[i]结尾的前缀 那么对于每个i而言,我们就是找出在1~i-1里面的和s[i]相匹配的前缀j 得到dp[i]=dp[j]+1(

Bob Lee's Blog For CS 897

Cartographer参数调优指南:如何用Lua配置解决建图漂移问题

本文深入解析Cartographer SLAM系统的Lua参数调优方法,针对建图漂移问题提供完整解决方案。从运动滤波、扫描匹配到多传感器融合,详细讲解关键参数配置技巧,并给出仓库物流和服务机器人等典型场景的优化方案,帮助开发者实现精准建图。

vulkan6gpu的博客 115

HDU—— 3336 Count the string

题意:给定一个字符串,duiyugaiz

u014086857的专栏 520

速腾Helios-16P使用Lego-loam实时构建点云地图(二)——Lego-loam的编译与运行

不兼容的问题,打开lego-loam的~/lego-loam_ws/src/LeGO-LOAM/LeGO-LOAM/src下的4个源码文件,搜索/camera_init,将所有/camera_init改成camera_init,也就是去掉斜杠,这样再回到工作空间重新编译lego-loam。3、速腾16线激光雷达RS-16 ----- 3D建图算法LeGO-LOAM的使用(Ubuntu18.04 + ROS Melodic)_速腾16线 lego loam_杰尼君的博客-优快云博客。

qq_59475883的博客 2567

YOLOv10改进策略【模型轻量化】| 替换骨干网络为MoblieNetV2,含模型详解和完整配置步骤

本文记录的是。采用深度可分离卷积将标准卷积分解为深度卷积和1×1卷积。同时,引入来,避免非线性层导致的性能下降问题。本文将应用到YOLOv10中,借助其高效的结构和特性,在保持一定精度的前提下,显著降低YOLOv10的计算复杂度和内存占用。

Limiiiing的博客 532

hdu3336 Count the string

Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1147    Accepted Submission(s): 494 Problem Description It is well kno

夏天的风 1749

基于STM32F103设计的智能门锁(支持多种开锁解锁方式)

这个智能锁模型是基于STM32平台开发的,支持多种开锁方式。其中,一种是使用RC522射频卡读卡器读取IC卡卡号和内部数据,并验证身份后开锁;另一种是通过连接蓝牙地址来确认业主身份,实现了蓝牙自动开锁功能;最后一种是通过ESP8266连接腾讯云物联网平台,并且用户可以通过微信小程序“腾讯连连”进行远程开锁和关锁。这样,用户就可以选择最方便的方式来进行开锁操作了。

3万+

hdu3336(KMP+DP)

题目链接:hdu3336 假设两串字符完全相等,next[j]=i,代表s[1...i]==sum[j-i+1....j],这一段其实就是前缀 i~j之间已经不可能有以j结尾的子串是前缀了,不然next【j】就不是 i 了 设dp【i】:以string[i]结尾的子串总共含前缀的数量 所以dp[j]=dp[i]+1,即以i结尾的子串中含前缀的数量加上前j个字符这一前缀 #includ

no pains,no gains 2929

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

hdu 3336 KMP之杭电next灵魂

hdu 3336

Myblackat的博客 526

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

hdu 3336(KMP算法的应用)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336 Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4844    Accepted Subm

T_T 742

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

HDU 3336 Count the string(KMP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336 解题思路: 先把原数组构造失配数组 fail[i] 表示0~i-1最长相同前后缀 首先我们先令ans = len,也就是先把每个前缀本身加上去 我们可以保证在fail数组所得到的后缀不会与这些重合,不然那叫前缀。 接下去遍历fail[2]~fail[len] 对于每个fail我们求...

shadiao.的博客 198

[HDU 3336] Count the string

题目传送-HDU3336 题意: 给你一个长度为\(n\)的字符串\(S\),问这个字符串的所有前缀在字符串中出现的次数之和(mod \(10007\)) \(n\le 200000\) 题解: 1.考虑KMP,并记录\(f_i\)表示以\(i\)为结尾的所有串中是前缀的个数,那么答案显然是所有\(f\)之和 根据KMP中nxt数组的定义,\(f_i=f_{nxt_i}+1\)(如果这里...

A4401780916的博客 117

kuangbin专题十六 KMP&&扩展KMP HDU3336 Count the string

kuangbin专题十六 KMP&amp;&amp;扩展KMP HDU3336 Count the string It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, ...

ACMerszl的博客 177

HDU 3336【前缀出现次数】dp+kmp

HDU 3336【前缀出现次数】dp+kmp 题意:求出字符串前缀出现的总次数,答案对1e4+7取模; 思路:我们先考虑kmp匹配前缀与自身,可惜是O(n*n)的复杂度,那么我们该怎样匹配呢?对于这样一个串, 我们可以很容易发现这样一件事cnt[s1]=cnt[s2]=cnt[s3]+1;我们初始化cnt[i]=1;然后从后往前累加cnt[nxt[i]]+=cnt[i],每出现一次长串,就...

qq_43653111的博客 410

kmp -- Count the string HDU - 3336

Count the string HDU - 3336 题意: T次询问,每次给你一个数 n 和字符串 s ,n为s的长度。问你s的所有前缀要和s串匹配时要比较多少次。 思路: next求出的就是和前缀匹配的最大长度,若长度大于0代表和前缀匹配,那么个数增加1,然后缩小前缀再进行判断。 如 ababa 当我们匹配到a的时候,得到的next[5] = 3, 这时候次数增加1, 再匹配一下next[3] = 1,值也大于0那么次数还要增加, 再匹配next[1] = 0, 等于0了代表没有前缀和它相等

dajiangyou123456的博客 157

hdu3336 扩展kmp

结合扩展kmp的知识 利用算两次思想,进而得到答案

m0_54646258的博客 209

hdu 3336 Count the string(KMP)

题目链接:hdu 3336 Count the string 题目大意:给出一个字符串,要求计算所有前缀串在该字符串中出现次数的总和。 解题思路:首先求出jump数组,然后对于每个位置来说,如果jump[p]!=0的话,即为存在一个前缀串,注意这里p = jump[p], 因为前缀串中含可能包含前缀串。最后要+n。 #include #include con

不慌不忙、不急不躁 1108

【HDU 3336 Count the string 】 KMP

HDU3336 本题题意为求字符串的每个前缀在整个字符串中的出现次数。 如果next[j]对答案有一个贡献,那么这个贡献在j中一定会再贡献一次,而且j为结尾的字符串对于总串产生的贡献只有长度为j的子串,(如果这个性质不懂,可以去看我的KMP总结专题性质二)于是我们可以得到转移方程ans[j]=ans[next[j]]+1ans[j]=ans[next[j]]+1ans[j]=ans[next[...

lajiyuan的博客 233

HDU 3336 Count The String

K - Count the string                                 HDU - 3336题意:例如abab这样的字符串的子字符串看为有a,ab,aba,abab四种,就是从第一个开始,每次加一个元素,也就是所有的非空前缀,其中a,ab在原字符串中出现两次,aba,abab各出现一次,所以一共六次,结果要%10007 对,每次都是从0开始更新,很慢分析一下这个a...

STOP 682

hdu3336解读KMP算法的next数组

贴代码不是目的,讲解算法才是关键!!。解题的思路是使用了 KMP 算法,然而把并不是完整的KMP算法。只用到了它的next数组的求法。然而这正是KMP算法本身的关键所在。这里关键在于讲解next数组的思想。 在漫天飞的网络资料中,next数组的表示方法大致有两种:

果冻虾仁 3225
上一篇: URAL - 1423
下一篇: (模板)Mac os下对拍程序
HumveeA6
博客等级 码龄17年 12粉丝 175原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值