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不分的症状.具体表现为—— 包大人在此高能预警:不想背单词,有可能你已经被传染了. 好好的,怎么突然不想背单词了 哈佛医学 ...
随机推荐
- K8S学习笔记之Kubernetes 配置管理 ConfigMap
0x00 概述 很多情况下我们为某一应用做好镜像,当我们想修改其中的一些参数的时候,就变得比较麻烦,又要重新制作镜像,我们是不是有一种方式,让镜像根据不同的场景调用我们不同的配置文件呢,那我们就需要用 ...
- RabbitMQ学习之RPC(6)
在第二个教程中,我们了解到如何在多个worker中使用Work Queues分发费时的任务. 但是,如果我们需要在远程运行一个函数并且等待结果该怎么办呢?这个时候,我们需要另外一个模式了.这种模式通常 ...
- 前端自动显示信息的小demo
效果: //来到这个页面立即请求,展示客户公司名称 $(function () { $.ajax({ type:"GET", url:"${pageContext.req ...
- Java自学-接口与继承 接口
设计Java的接口 在设计LOL的时候,进攻类英雄有两种,一种是进行物理系攻击,一种是进行魔法系攻击 这时候,就可以使用接口来实现这个效果. 接口就像是一种约定,我们约定某些英雄是物理系英雄,那么他们 ...
- js高频经典面试题总结
类型转换问题 console.log(null>=0); console.log(null<=0); console.log(null==0); console.log(undefined ...
- Python操作SQLite/MySQL/LMDB
1.概述 1.1前言 最近在存储字模图像集的时候,需要学习LMDB,趁此机会复习了SQLite和MySQL的使用,一起整理在此. 1.2环境 使用win7,Python 3.5.2. 2.SQLite ...
- 标记重要和强调的文本 strong & em
strong元素表示内容的重要性,而em则表示内容的着重点. 根据内容需要,这两个元素既可以单独使用,也可以一起使用. 例如: ... <body> <p><strong ...
- JavaScript 之 location 对象
一.location 对象 location 对象是 window 对象下的一个属性,使用的时候可以省略 window 对象. 常用属性: location.href = 'http://www.ba ...
- Android Drawable和Bitmap区别
一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...
- C#8.0—非空引用类型
非空引用类型--C#8.0 原文地址:https://devblogs.microsoft.com/dotnet/try-out-nullable-reference-types/?utm_sourc ...