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 阅读详情

相关推荐

数字化车间智能排产调度挑战赛(一)—— 数学模型

科大讯飞——数字化车间智能排产调度挑战赛。

Lyyyp的博客 5649

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

visual studio 2017编译Triangle库遇到的问题和解决办法

这段时间因为一个项目需要使用到Triangle这个三角剖分工具,需要在windows环境下进行对源码编译,中间踩了很多坑,特此记录下。 1、下载 下载链接是下边这个,需要翻墙 http://www.cs.cmu.edu/~quake/triangle.html 2、编译。。超。。。级。。。麻。。。烦。。。 在ubutu下安装一切顺利,完全没遇到什么麻烦,但是换到windows下就麻烦不断...

csubai07的博客 2438

HDU(3336)

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

m0_52262443的博客 444

【中兴交换机MC-LAG配置】

​ 中兴mc-lag配置 主设备配置如下: Keepalive链路 interface smartgroup1023 //用作MC-LAG的Keepalive链路接口 switch attribute disable yes description For_Keepalived exit interface xgei-0/1/1/47 switch attribute disable yes description For_Keepalived exit interface

qq_31440733的博客 1万+

完整内、外期货量化交易系统源码可售

支持客户登录校验,支持所有的实时行情和汇总报价功能、实时资讯(报价,列表,分时,分钟成交明晰,),多线程支持盘后收盘作业下载(日线,5分钟线,15分钟, 30分钟,60分钟线,),支持从服务器下载相关运行配置(来自服务器动态配置信息,如收盘日期等),实现状态条显示。收盘作业包括日线、5分钟线、15分钟线、30分钟、60分钟线、2小时线、4小时线每日分时走势。综合信息栏显示用户账户信息、合约信息、当日委托单记录、当日成交记录、当日平仓记录、当日跟单记录、当日(月/周)排行榜、下单栏、持仓信息;

qq_35600909的博客 1805

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

从5V降到3.3V,你的LDO到底有多烫?手把手算功耗、选散热,避开这些坑

本文详细解析了LDO在5V转3.3V电路中的发热问题,提供了精确的功耗计算公式和散热设计方法。通过对比不同封装的热阻参数和优化PCB布局,帮助工程师有效降低LDO温度,避免热保护触发。文章还探讨了替代方案的技术拐点,为电源系统优化设计提供实用指导。

weixin_30304375的博客 435

HDU—— 3336 Count the string

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

u014086857的专栏 520

仿真每日一练 | 有限元模态分析详解

结构的振动一直是工业领域产品分析的重点,在振动的仿真分析中,模态分析是其最基本的分析类型,通过研究结构的固有频率和振型对产品的设计提供指导。2.2、在interaction模块,通过special->Spring,在各点之间分别创建弹簧单元,弹簧刚度为1000。2.1、在interaction模块,创建两个RP点,与两侧RP点各间隔100大小,如图3所示;其中M、K、C均为n*n的矩阵,s、x、v为n*1的矢量,n为系统自由度数量。3、在Assembly模块创建装配体,两点之间的距离为100,如图2所示;

ansysxuexizhe的博客 1655

【32】OpenCV——图像含义关系?RGGB , BGGR , GRBG , GBRG呢?raw8,raw10,raw12,raw14呢? YUV422; RAW16呢?YCbYCr/RG_GB;

‌如前所述,定义原始数据的位深精度。‌* ‌一种压缩色彩编码方式,通过色度抽样(亮度Y全分辨率,色度U/V半分辨率)减少数据量,常用于视频传输。‌* ‌可能指每个像素分量占16位存储(如高位填充的RAW10/12/14),或未明确量化的高精度原始数据。‌ ‌分类‌核心定义‌关联性及典型应用传感器原始色彩排列(RGGB/BGGR等)决定RAW数据的色彩分布规则RAW位深每个分量的数据精度(8/10/12/14位)影响动态范围和存储空间‌YUV422。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 793

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

Wsl/InstallDistro/Service/RegisterDistro/CreateVm/HCS/E_INVALIDARG

摘要:安装WSL2时遇到E_INVALIDARG错误(多核CPU问题),可通过创建.wslconfig配置文件解决。配置内容包括:渐进式内存回收、自动代理、模拟虚拟系统调用、限制内存为4GB和处理器核心数为4。需确保已启用虚拟机平台和Linux子系统功能。 (98字)

猿小白的博客 1047

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

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

hdu 3336 KMP之杭电next灵魂

hdu 3336

Myblackat的博客 526

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

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

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

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、付费专栏及课程。

余额充值