二次联通门 : 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 背单词的更多相关文章

  1. 洛谷 P2353 背单词

    题目背景 小明对英语一窍不通,令老师十分头疼.于是期末考试前夕,小明被逼着开始背单词…… 题目描述 老师给了小明一篇长度为N的英语文章,然后让小明背M个单词.为了确保小明不会在背单词时睡着,老师会向他 ...

  2. AC日记——背单词 洛谷 P2353

    背单词 思路: KMP+统计前缀和优化: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1000005 ], ...

  3. [SCOI2016]背单词——trie树相关

    题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...

  4. [SCOI2016]背单词 题解

    背单词 https://www.luogu.com.cn/problem/P3294 前言: Trie树的省选题(瑟瑟发抖QAQ) 问题汇总:(请忽略) (1)对Trie字典树的运用不熟练 (2)没想 ...

  5. 做中学(Learning by Doing)之背单词-扇贝网推荐

    做中学(Learning by Doing)之背单词-扇贝网推荐 看完杨贵福老师(博客,知乎专栏,豆瓣)的「继续背单词,8个月过去了」,我就有写这篇文章的冲动了,杨老师说: 有时候我会感觉非常后悔,如 ...

  6. “我爱背单词”beta版发布与使用说明

    我爱背单词BETA版本发布 第二轮迭代终于画上圆满句号,我们的“我爱背单词”beta版本已经发布. Beta版本说明 项目名称 我爱背单词 版本 Beta版 团队名称 北京航空航天大学计算机学院  拒 ...

  7. BZOJ4567[Scoi2016]背单词

    4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...

  8. 《我爱背单词》 Alpha版 发布说明

    ——发布地址(baidu网盘) http://pan.baidu.com/s/15omtB ——简介  <我爱背单词>是一款英语单词记忆和管理辅助软件,旨在帮助广大考生在短期内攻克GRE. ...

  9. [No000057]一个人默默背单词,小心被传染哦

    不日凛冬将至,全国各地,已有多名少侠因季节变化,出现了不同程度的四肢不勤.bd不分的症状.具体表现为—— 包大人在此高能预警:不想背单词,有可能你已经被传染了. 好好的,怎么突然不想背单词了 哈佛医学 ...

随机推荐

  1. InstantiationAwareBeanPostProcessor 分析

    Cglib之Enhancer创建动态代理https://blog.csdn.net/yaomingyang/article/details/82762697 https://blog.csdn.net ...

  2. DES加密 java与.net可以相互加密解密两种方法

    DES加密 java与.net可以相互加密解密两种方法 https://www.cnblogs.com/DrWang/archive/2011/03/30/2000124.html sun.misc. ...

  3. 8、VUE自定义组件

    1.为什么要使用自定义组件? 自定义组件是用来封装复杂的内容,提高可重用性,比如封装复杂的表格组件.日历组件.图片轮播组件等. 2.自定义组件 2.1. 全局组件 全局组件是每个Vue对象都能使用的组 ...

  4. asp.net core web的导入导出excel功能

    这里主要记录下asp.net core web页面上进行导入导出excel的操作. 主要是导入,因为现在使用的很多前端框架(例如kendo ui)本身就有导出的功能. 这里使用到EPPlus.Core ...

  5. C# vb .net图像合成-合成椭圆

    在.net中,如何简单快捷地实现图像合成呢,比如合成文字,合成艺术字,多张图片叠加合成等等?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码 ...

  6. 彻底理解javascript中的this指针

    http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/ https://www.benn ...

  7. 运维利器1-supervisor

    supervisor用来管理进程服务很方便 优点: 1.重启方便,无抖动感 2.可以分组管理进程 3.加入系统自动启动后,可以开机自启,程序异常退出能自动启动 操作: 1.在python沙箱环境下操作 ...

  8. PAT 1003我要通过!

    PAT 1003 我要通过! 答案正确"是自动判题系统给出的最令人欢喜的回复.本题属于 PAT 的"答案正确"大派送 -- 只要读入的字符串满足下列条件,系统就输出&qu ...

  9. 当前标识(IIS APPPOOL\DefaultAppPool)没有对“C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files”的写访问权限

    找到或增加这个目录,给他增加权限.

  10. mysql 获取指定日期到指定日期 区间段的日期

    第一种方法: cross join (就相当于mysql中的循环) CROSS JOIN 把两张表中的数据进行 N * M的组合,即笛卡尔积 这里的两张表利用 union all都有5条数据,所以进行 ...