luogu P2353 背单词
二次联通门 : luogu P2353 背单词
一眼看过去, 卧槽,AC自动机板子题
写完后T成SB
卧槽10^6 做个篮子啊
重构思路。。。
恩。。Hash + 莫队。。。
恶心啊。。
找xxy dalao, AC自动机 + 前缀和
码完WA成SB
去群里找dalao
大佬告诉了我前缀和的正确使用姿势。。。
然后就依然WA成SB

做个毛线
贴一个AC自动机的30代码
#include <cstdio>
#include <cstring>
#include <queue> #define Max 3000090 void read (int &now)
{
now = ;
register char word = getchar ();
while (word < '' || word > '')
word = getchar ();
while (word >= '' && word <= '')
{
now = now * + word - '';
word = getchar ();
}
} char __txt[Max]; struct T_D
{
T_D *child[]; T_D *Fail;
int Count; int number;
T_D ()
{
for (int i = ; i < ; i ++)
this->child[i] = NULL; Count = ;
Fail = NULL;
number = ;
}
}; int List[Max << ];
int List_Cur; bool visit[Max]; class AC_Type
{ private : T_D *Root;
int Trie_Count; public : void Insert (char *key)
{
T_D *now = Root; int Len = strlen (key);
int Id; for (int i = ; i < Len; i ++)
{
Id = key[i] - 'a';
if (now->child[Id] == NULL)
{
now->child[Id] = new T_D;
now->child[Id]->number = ++ Trie_Count;
} now = now->child[Id];
}
now->Count ++;
} AC_Type ()
{
Trie_Count = ;
Root = new T_D ;
Root->number = ++ Trie_Count;
} void Build_AC ()
{
std :: queue <T_D *> Queue; Queue.push (Root); T_D *now, *pos;
while (!Queue.empty ())
{
now = Queue.front ();
Queue.pop (); pos = NULL; for (int i = ; i < ; i ++)
{
if (now->child[i] == NULL)
continue;
if (now == Root)
now->child[i]->Fail = Root;
else
{
for (pos = now->Fail; pos; pos = pos->Fail)
if (pos->child[i])
{
now->child[i]->Fail = pos->child[i];
break;
}
if (pos == NULL)
now->child[i]->Fail = Root;
}
Queue.push (now->child[i]);
}
}
} int Query (int x, int y)
{
T_D *now, *pos; int Id ;
now = Root;
int res = ; for (int i = x; i <= y; i ++)
{
Id = __txt[i] - 'a';
for (; now != Root && now->child[Id] == NULL; now = now->Fail); now = now->child[Id];
if (now == NULL)
now = Root; for (pos = now; pos != Root && !visit[pos->number]; pos = pos->Fail)
{
res += pos->Count;
visit[pos->number] = true;
List[++ List_Cur] = pos->number;
} for (int j = ; j <= List_Cur; j ++)
visit[List[j]] = false; List_Cur = ; } return res;
} }; AC_Type Make; int N, Q;
char line[Max]; int main (int argc, char *argv[])
{
read (N);
read (Q);
scanf ("%s", __txt); for (int i = ; i <= N; i ++)
{
scanf ("%s", line);
Make.Insert (line);
} Make.Build_AC (); for (int x, y; Q --; )
{
read (x);
read (y); printf ("%d\n", Make.Query (-- x, -- y));
} return ;
}
再贴个AC自动机思路正确但由于细节问题WA成dog的代码
#include <cstdio>
#include <cstring>
#include <queue> #define Max 1000090 #define DEBUG for (int i = 1; i <= strlen (__txt); i ++)\
printf ("%d ", __sum[i]);\
putchar ('\n'); void read (int &now)
{
now = ;
register char word = getchar ();
while (word < '' || word > '')
word = getchar ();
while (word >= '' && word <= '')
{
now = now * + word - '';
word = getchar ();
}
} char __txt[Max]; struct T_D
{
T_D *child[]; T_D *Fail;
int Count; int number;
T_D ()
{
for (int i = ; i < ; i ++)
this->child[i] = NULL; Count = ;
Fail = NULL;
number = ;
}
}; int __sum[Max]; class AC_Type
{ private : T_D *Root;
int Trie_Count; public : void Insert (char *key)
{
T_D *now = Root; int Len = strlen (key);
int Id; for (register int i = ; i < Len; i ++)
{
Id = key[i] - 'a';
if (now->child[Id] == NULL)
{
now->child[Id] = new T_D;
now->child[Id]->number = ++ Trie_Count;
} now = now->child[Id];
}
now->Count ++;
} AC_Type ()
{
Trie_Count = ;
Root = new T_D ;
Root->number = ++ Trie_Count;
} void Build_AC ()
{
std :: queue <T_D *> Queue; Queue.push (Root); T_D *now, *pos;
while (!Queue.empty ())
{
now = Queue.front ();
Queue.pop (); pos = NULL; for (register int i = ; i < ; i ++)
{
if (now->child[i] == NULL)
continue;
if (now == Root)
now->child[i]->Fail = Root;
else
{
for (pos = now->Fail; pos; pos = pos->Fail)
if (pos->child[i])
{
now->child[i]->Fail = pos->child[i];
break;
}
if (pos == NULL)
now->child[i]->Fail = Root;
}
Queue.push (now->child[i]);
}
}
} int Query ()
{
T_D *now, *pos; int Id ;
now = Root;
int res = ;
int Len = strlen (__txt); for (register int i = ; i < Len; i ++)
{
Id = __txt[i] - 'a';
for ( ; now != Root && now->child[Id] == NULL; now = now->Fail); now = now->child[Id];
if (now == NULL)
now = Root; for (pos = now; pos != Root && pos->Count >= ; pos = pos->Fail)
{
__sum[i + ] += pos->Count;
pos->Count = -;
}
__sum[i + ] += __sum[i]; } return res;
} }; AC_Type Make; int N, Q;
char line[Max]; int length[Max]; int main (int argc, char *argv[])
{ read (N);
read (Q);
scanf ("%s", __txt); for (int i = ; i <= N; i ++)
{
scanf ("%s", line);
Make.Insert (line);
length[i] = strlen (line);
} Make.Build_AC ();
Make.Query ();
register int Answer, now; for (int x, y; Q --; )
{
Answer = ; read (x);
read (y); for (int i = ; i <= N; i ++)
Answer += (__sum[y - length[i]] - __sum[x - ]); printf ("%d\n", Answer);
} return ;
}
最后再贴个正解。。。。是我想麻烦了。。kmp或者hash都可以。。
/*
luogu P2353 背单词 由于M很小
可以进行M次kmp 统计出M个前缀和 每次输出时把 M 个前缀和扫一遍
注意区间的开闭问题 由于r端点的串不包含在所查询的区间内
所以要减去当前模式串的长度 */
#include <cstdio>
#include <cstring> #define Max 1000090 void read (int &now)
{
now = ;
register char word = getchar ();
while (word > '' || word < '')
word = getchar ();
while (word >= '' && word <= '')
{
now = now * + word - '';
word = getchar ();
}
} int __next[Max]; void Get_Next (char *line)
{
__next[] = -; for (int pos_1 = , pos_2 = -, Len = strlen (line); pos_1 < Len; )
if (pos_2 == - || line[pos_1] == line[pos_2])
{
pos_1 ++;
pos_2 ++;
__next[pos_1] = pos_2;
}
else
pos_2 = __next[pos_2]; } int __sum[Max][Max / + ]; void Kmp (char *line, char *__txt, int number)
{
for (int Len_txt = strlen (__txt), Len = strlen (line), pos_1 = , pos_2 = ; pos_1 <= Len_txt; )
{
if (pos_2 == - || __txt[pos_1] == line[pos_2])
{
pos_1 ++;
pos_2 ++;
}
else
pos_2 = __next[pos_2];
if (pos_2 == Len)
{
__sum[pos_1][number] ++;
pos_2 = __next[pos_2];
}
}
} char __txt[Max]; int length[Max];
char line[Max]; int main (int argc, char *argv[])
{
int N, M; read (N);
read (M); scanf ("%s", __txt); int Len_txt = strlen (__txt); for (int i = ; i <= N; i ++)
{
scanf ("%s", line); Get_Next (line);
Kmp (line, __txt, i); length[i] = strlen (line);
} for (int i = ; i <= Len_txt; i ++) // 把每个模式串的前缀和分开存
for (int j = ; j <= N; j ++)
__sum[i][j] += __sum[i - ][j]; for (int i = , x, y, Answer; i <= M; i ++)
{
read (x);
read (y);
Answer = ; for (int j = ; j <= N; j ++)
if (x - <= y - length[j])
Answer += __sum[y][j] - __sum[x + length[j] - ][j]; printf ("%d\n", Answer);
}
return ;
}
luogu P2353 背单词的更多相关文章
- 洛谷 P2353 背单词
题目背景 小明对英语一窍不通,令老师十分头疼.于是期末考试前夕,小明被逼着开始背单词…… 题目描述 老师给了小明一篇长度为N的英语文章,然后让小明背M个单词.为了确保小明不会在背单词时睡着,老师会向他 ...
- AC日记——背单词 洛谷 P2353
背单词 思路: KMP+统计前缀和优化: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1000005 ], ...
- [SCOI2016]背单词——trie树相关
题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...
- [SCOI2016]背单词 题解
背单词 https://www.luogu.com.cn/problem/P3294 前言: Trie树的省选题(瑟瑟发抖QAQ) 问题汇总:(请忽略) (1)对Trie字典树的运用不熟练 (2)没想 ...
- 做中学(Learning by Doing)之背单词-扇贝网推荐
做中学(Learning by Doing)之背单词-扇贝网推荐 看完杨贵福老师(博客,知乎专栏,豆瓣)的「继续背单词,8个月过去了」,我就有写这篇文章的冲动了,杨老师说: 有时候我会感觉非常后悔,如 ...
- “我爱背单词”beta版发布与使用说明
我爱背单词BETA版本发布 第二轮迭代终于画上圆满句号,我们的“我爱背单词”beta版本已经发布. Beta版本说明 项目名称 我爱背单词 版本 Beta版 团队名称 北京航空航天大学计算机学院 拒 ...
- BZOJ4567[Scoi2016]背单词
4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...
- 《我爱背单词》 Alpha版 发布说明
——发布地址(baidu网盘) http://pan.baidu.com/s/15omtB ——简介 <我爱背单词>是一款英语单词记忆和管理辅助软件,旨在帮助广大考生在短期内攻克GRE. ...
- [No000057]一个人默默背单词,小心被传染哦
不日凛冬将至,全国各地,已有多名少侠因季节变化,出现了不同程度的四肢不勤.bd不分的症状.具体表现为—— 包大人在此高能预警:不想背单词,有可能你已经被传染了. 好好的,怎么突然不想背单词了 哈佛医学 ...
随机推荐
- Java开发月薪2W的知乎讨论记录截取
1. 推荐看 作者:匿名用户 链接:https://www.zhihu.com/question/39890405/answer/83676977 来源:知乎 著作权归作者所有.商业转载请联系作者获得 ...
- Tomcat 类加载器的实现
Tomcat 内部定义了多个 ClassLoader,以便应用和容器访问不同存储库中的类和资源,同时达到应用间类隔离的目的.本文首发于公众号:顿悟源码. 1. Java 类加载机制 类加载就是把编译生 ...
- 手机端 关闭当前页面的JS
JS 代码如下 PS:我找的原代码中, 注释部分是没有注释的,但是调试的时候报错,就注释掉了,因为我只需要微信和支付宝的判定,所以这个地方,就没仔细研究 var isLppzApp = false ...
- vs2017添加引用提示“找不到 Microsoft.VisualStudio.Shell.Interop.IVsReferenceManager 服务的实例”解决方案
vs2017添加引用提示“找不到 Microsoft.VisualStudio.Shell.Interop.IVsReferenceManager 服务的实例” 不知道是不是安装时候的问题?解决方法: ...
- Go的基础类型
1. 命名 Go语言中的函数名.变量名.常量名.类型名.语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母.数字或 ...
- FPGA的电源选择重要性分析
米尔Z-Turn Board 7Z010(20)板卡体验有感:IF"> FPGA的电源需求通常很复杂,因为FPGA有多达至少三种供电要求,为了实现可靠的系统性能,必须对这些要求排序. ...
- Java深入学习(1):多线程
多线程目的:在同一时刻有多条不同路径执行程序,提高程序运行效率 多线程应用:数据库连接池,多线程文件下载等 注意:在文件下载中使用多线程,无法提高速度 在一个进程中,一定会有主线程 从基础开始,多线程 ...
- Vue 中 $nextTick() 的应用
Vue 在更新 DOM 时是异步执行的. 只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更.如果同一个 watcher 被多次触发,只会被推入到队列中一次.这种在缓 ...
- OCR6:Custom Traineddata
参考:https://groups.google.com/forum/#!msg/tesseract-ocr/MSYezIbckvs/kO1VoNKMDMQJ V4版本代码示例 : import py ...
- Mac pro操作快捷键
1. 在Finder顶部显示文件/文件夹全路径 终端里输入:defaults write com.apple.finder _FXShowPosixPathInTitle -bool TRUE;kil ...