首页 > 代码库 > luogu P2353 背单词
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 = 0; register char word = getchar (); while (word < ‘0‘ || word > ‘9‘) word = getchar (); while (word >= ‘0‘ && word <= ‘9‘) { now = now * 10 + word - ‘0‘; word = getchar (); } } char __txt[Max]; struct T_D { T_D *child[26]; T_D *Fail; int Count; int number; T_D () { for (int i = 0; i < 26; i ++) this->child[i] = NULL; Count = 0; Fail = NULL; number = 0; } }; int List[Max << 1]; 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 = 0; 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 = 0; 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 = 0; i < 26; 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 = 0; 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 = 1; j <= List_Cur; j ++) visit[List[j]] = false; List_Cur = 0; } 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 = 1; 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 0; }
再贴个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 = 0; register char word = getchar (); while (word < ‘0‘ || word > ‘9‘) word = getchar (); while (word >= ‘0‘ && word <= ‘9‘) { now = now * 10 + word - ‘0‘; word = getchar (); } } char __txt[Max]; struct T_D { T_D *child[26]; T_D *Fail; int Count; int number; T_D () { for (int i = 0; i < 26; i ++) this->child[i] = NULL; Count = 0; Fail = NULL; number = 0; } }; 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 = 0; 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 = 0; 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 = 0; i < 26; 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 = 0; int Len = strlen (__txt); for (register int i = 0; 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 >= 0; pos = pos->Fail) { __sum[i + 1] += pos->Count; pos->Count = -1; } __sum[i + 1] += __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 = 1; 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 = 0; read (x); read (y); for (int i = 1; i <= N; i ++) Answer += (__sum[y - length[i]] - __sum[x - 1]); printf ("%d\n", Answer); } return 0; }
最后再贴个正解。。。。是我想麻烦了。。kmp或者hash都可以。。
luogu P2353 背单词
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。